summaryrefslogtreecommitdiffabout
path: root/libetpan
Unidiff
Diffstat (limited to 'libetpan') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/COPYRIGHT28
-rw-r--r--libetpan/config.h119
-rw-r--r--libetpan/include/libetpan/carray.h123
-rw-r--r--libetpan/include/libetpan/charconv.h67
-rw-r--r--libetpan/include/libetpan/chash.h165
-rw-r--r--libetpan/include/libetpan/cinthash.h69
-rw-r--r--libetpan/include/libetpan/clist.h133
-rw-r--r--libetpan/include/libetpan/data_message_driver.h50
-rw-r--r--libetpan/include/libetpan/dbdriver.h53
-rw-r--r--libetpan/include/libetpan/dbdriver_message.h52
-rw-r--r--libetpan/include/libetpan/dbdriver_types.h71
-rw-r--r--libetpan/include/libetpan/dbstorage.h61
-rw-r--r--libetpan/include/libetpan/generic_cache_types.h56
-rw-r--r--libetpan/include/libetpan/hotmailstorage.h56
-rw-r--r--libetpan/include/libetpan/imapdriver.h52
-rw-r--r--libetpan/include/libetpan/imapdriver_cached.h52
-rw-r--r--libetpan/include/libetpan/imapdriver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/imapdriver_message.h52
-rw-r--r--libetpan/include/libetpan/imapdriver_types.h144
-rw-r--r--libetpan/include/libetpan/imapstorage.h90
-rw-r--r--libetpan/include/libetpan/libetpan-config.h7
-rw-r--r--libetpan/include/libetpan/libetpan.h119
-rw-r--r--libetpan/include/libetpan/libetpan_version.h57
-rw-r--r--libetpan/include/libetpan/mail.h56
-rw-r--r--libetpan/include/libetpan/maildir.h67
-rw-r--r--libetpan/include/libetpan/maildir_types.h91
-rw-r--r--libetpan/include/libetpan/maildirdriver.h53
-rw-r--r--libetpan/include/libetpan/maildirdriver_cached.h53
-rw-r--r--libetpan/include/libetpan/maildirdriver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/maildirdriver_message.h52
-rw-r--r--libetpan/include/libetpan/maildirdriver_types.h96
-rw-r--r--libetpan/include/libetpan/maildirstorage.h69
-rw-r--r--libetpan/include/libetpan/maildriver.h546
-rw-r--r--libetpan/include/libetpan/maildriver_errors.h102
-rw-r--r--libetpan/include/libetpan/maildriver_types.h795
-rw-r--r--libetpan/include/libetpan/maildriver_types_helper.h99
-rw-r--r--libetpan/include/libetpan/mailengine.h190
-rw-r--r--libetpan/include/libetpan/mailfolder.h70
-rw-r--r--libetpan/include/libetpan/mailimap.h598
-rw-r--r--libetpan/include/libetpan/mailimap_helper.h66
-rw-r--r--libetpan/include/libetpan/mailimap_socket.h54
-rw-r--r--libetpan/include/libetpan/mailimap_ssl.h54
-rw-r--r--libetpan/include/libetpan/mailimap_types.h3274
-rw-r--r--libetpan/include/libetpan/mailimap_types_helper.h758
-rw-r--r--libetpan/include/libetpan/mailimf.h347
-rw-r--r--libetpan/include/libetpan/mailimf_types.h793
-rw-r--r--libetpan/include/libetpan/mailimf_types_helper.h370
-rw-r--r--libetpan/include/libetpan/mailimf_write_file.h169
-rw-r--r--libetpan/include/libetpan/mailimf_write_generic.h142
-rw-r--r--libetpan/include/libetpan/mailimf_write_mem.h135
-rw-r--r--libetpan/include/libetpan/mailmbox.h144
-rw-r--r--libetpan/include/libetpan/mailmbox_types.h143
-rw-r--r--libetpan/include/libetpan/mailmessage.h379
-rw-r--r--libetpan/include/libetpan/mailmessage_types.h50
-rw-r--r--libetpan/include/libetpan/mailmh.h152
-rw-r--r--libetpan/include/libetpan/mailmime.h102
-rw-r--r--libetpan/include/libetpan/mailmime_content.h89
-rw-r--r--libetpan/include/libetpan/mailmime_decode.h55
-rw-r--r--libetpan/include/libetpan/mailmime_disposition.h62
-rw-r--r--libetpan/include/libetpan/mailmime_types.h440
-rw-r--r--libetpan/include/libetpan/mailmime_types_helper.h165
-rw-r--r--libetpan/include/libetpan/mailmime_write_file.h105
-rw-r--r--libetpan/include/libetpan/mailmime_write_generic.h73
-rw-r--r--libetpan/include/libetpan/mailmime_write_mem.h73
-rw-r--r--libetpan/include/libetpan/mailpop3.h101
-rw-r--r--libetpan/include/libetpan/mailpop3_helper.h64
-rw-r--r--libetpan/include/libetpan/mailpop3_socket.h54
-rw-r--r--libetpan/include/libetpan/mailpop3_ssl.h54
-rw-r--r--libetpan/include/libetpan/mailpop3_types.h107
-rw-r--r--libetpan/include/libetpan/mailprivacy.h117
-rw-r--r--libetpan/include/libetpan/mailprivacy_gnupg.h46
-rw-r--r--libetpan/include/libetpan/mailprivacy_smime.h84
-rw-r--r--libetpan/include/libetpan/mailprivacy_tools.h102
-rw-r--r--libetpan/include/libetpan/mailprivacy_types.h82
-rw-r--r--libetpan/include/libetpan/mailsem.h51
-rw-r--r--libetpan/include/libetpan/mailsmtp.h94
-rw-r--r--libetpan/include/libetpan/mailsmtp_helper.h74
-rw-r--r--libetpan/include/libetpan/mailsmtp_socket.h56
-rw-r--r--libetpan/include/libetpan/mailsmtp_ssl.h55
-rw-r--r--libetpan/include/libetpan/mailsmtp_types.h126
-rw-r--r--libetpan/include/libetpan/mailstorage.h99
-rw-r--r--libetpan/include/libetpan/mailstorage_types.h203
-rw-r--r--libetpan/include/libetpan/mailstream.h73
-rw-r--r--libetpan/include/libetpan/mailstream_helper.h77
-rw-r--r--libetpan/include/libetpan/mailstream_low.h62
-rw-r--r--libetpan/include/libetpan/mailstream_socket.h61
-rw-r--r--libetpan/include/libetpan/mailstream_ssl.h59
-rw-r--r--libetpan/include/libetpan/mailstream_types.h87
-rw-r--r--libetpan/include/libetpan/mailthread.h108
-rw-r--r--libetpan/include/libetpan/mailthread_types.h64
-rw-r--r--libetpan/include/libetpan/mboxdriver.h52
-rw-r--r--libetpan/include/libetpan/mboxdriver_cached.h54
-rw-r--r--libetpan/include/libetpan/mboxdriver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/mboxdriver_message.h52
-rw-r--r--libetpan/include/libetpan/mboxdriver_types.h107
-rw-r--r--libetpan/include/libetpan/mboxstorage.h69
-rw-r--r--libetpan/include/libetpan/mhdriver.h52
-rw-r--r--libetpan/include/libetpan/mhdriver_cached.h52
-rw-r--r--libetpan/include/libetpan/mhdriver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/mhdriver_message.h52
-rw-r--r--libetpan/include/libetpan/mhdriver_types.h100
-rw-r--r--libetpan/include/libetpan/mhstorage.h67
-rw-r--r--libetpan/include/libetpan/mime_message_driver.h53
-rw-r--r--libetpan/include/libetpan/mmapstring.h136
-rw-r--r--libetpan/include/libetpan/newsnntp.h187
-rw-r--r--libetpan/include/libetpan/newsnntp_socket.h55
-rw-r--r--libetpan/include/libetpan/newsnntp_ssl.h55
-rw-r--r--libetpan/include/libetpan/newsnntp_types.h144
-rw-r--r--libetpan/include/libetpan/nntpdriver.h52
-rw-r--r--libetpan/include/libetpan/nntpdriver_cached.h52
-rw-r--r--libetpan/include/libetpan/nntpdriver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/nntpdriver_message.h52
-rw-r--r--libetpan/include/libetpan/nntpdriver_types.h146
-rw-r--r--libetpan/include/libetpan/nntpstorage.h93
-rw-r--r--libetpan/include/libetpan/pop3driver.h52
-rw-r--r--libetpan/include/libetpan/pop3driver_cached.h52
-rw-r--r--libetpan/include/libetpan/pop3driver_cached_message.h52
-rw-r--r--libetpan/include/libetpan/pop3driver_message.h52
-rw-r--r--libetpan/include/libetpan/pop3driver_types.h153
-rw-r--r--libetpan/include/libetpan/pop3storage.h95
-rw-r--r--libetpan/libetpan-config.h7
-rw-r--r--libetpan/libetpan.pro450
-rw-r--r--libetpan/libetpanE.pro450
-rw-r--r--libetpan/src/data-types/base64.c143
-rw-r--r--libetpan/src/data-types/base64.h59
-rw-r--r--libetpan/src/data-types/carray.c142
-rw-r--r--libetpan/src/data-types/carray.h123
-rw-r--r--libetpan/src/data-types/charconv.c251
-rw-r--r--libetpan/src/data-types/charconv.h67
-rw-r--r--libetpan/src/data-types/chash.c394
-rw-r--r--libetpan/src/data-types/chash.h165
-rw-r--r--libetpan/src/data-types/cinthash.c248
-rw-r--r--libetpan/src/data-types/cinthash.h69
-rw-r--r--libetpan/src/data-types/clist.c265
-rw-r--r--libetpan/src/data-types/clist.h133
-rw-r--r--libetpan/src/data-types/connect.c86
-rw-r--r--libetpan/src/data-types/connect.h54
-rw-r--r--libetpan/src/data-types/hmac-md5.h94
-rw-r--r--libetpan/src/data-types/mail.h56
-rw-r--r--libetpan/src/data-types/mail_cache_db.c403
-rw-r--r--libetpan/src/data-types/mail_cache_db.h148
-rw-r--r--libetpan/src/data-types/mail_cache_db_types.h52
-rw-r--r--libetpan/src/data-types/maillock.c301
-rw-r--r--libetpan/src/data-types/maillock.h53
-rw-r--r--libetpan/src/data-types/mailsem.c114
-rw-r--r--libetpan/src/data-types/mailsem.h51
-rw-r--r--libetpan/src/data-types/mailstream.c399
-rw-r--r--libetpan/src/data-types/mailstream.h73
-rw-r--r--libetpan/src/data-types/mailstream_helper.c515
-rw-r--r--libetpan/src/data-types/mailstream_helper.h77
-rw-r--r--libetpan/src/data-types/mailstream_low.c164
-rw-r--r--libetpan/src/data-types/mailstream_low.h62
-rw-r--r--libetpan/src/data-types/mailstream_socket.c238
-rw-r--r--libetpan/src/data-types/mailstream_socket.h61
-rw-r--r--libetpan/src/data-types/mailstream_ssl.c320
-rw-r--r--libetpan/src/data-types/mailstream_ssl.h59
-rw-r--r--libetpan/src/data-types/mailstream_types.h87
-rw-r--r--libetpan/src/data-types/mapping.c67
-rw-r--r--libetpan/src/data-types/mapping.h54
-rw-r--r--libetpan/src/data-types/md5.c570
-rw-r--r--libetpan/src/data-types/md5.h88
-rw-r--r--libetpan/src/data-types/md5global.h79
-rw-r--r--libetpan/src/data-types/mmapstring.c551
-rw-r--r--libetpan/src/data-types/mmapstring.h136
-rw-r--r--libetpan/src/driver/TODO9
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.c119
-rw-r--r--libetpan/src/driver/implementation/data-message/data_message_driver.h50
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.c1134
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.h53
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.c308
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver_types.h71
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.c144
-rw-r--r--libetpan/src/driver/implementation/db/dbstorage.h61
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.c62
-rw-r--r--libetpan/src/driver/implementation/hotmail/hotmailstorage.h56
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.c1226
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.c1370
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.c664
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.c1239
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.c3623
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.h116
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_types.h144
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.c297
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.h90
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.c676
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.c1158
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c334
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.c255
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.c198
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_tools.h53
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_types.h96
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.c193
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.c515
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.c1337
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached.h54
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c361
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.c225
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.c435
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.h85
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_types.h107
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxstorage.h69
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.c875
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.c1315
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.c338
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.c213
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.c484
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.h80
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_types.h100
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.c192
-rw-r--r--libetpan/src/driver/implementation/mh/mhstorage.h67
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.c914
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.h53
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.c1180
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.c1059
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c365
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.c169
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.c563
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_tools.h88
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpdriver_types.h146
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.c267
-rw-r--r--libetpan/src/driver/implementation/nntp/nntpstorage.h93
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.c388
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.c899
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c355
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.c193
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_message.h52
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.c344
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_tools.h82
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_types.h153
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.c284
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3storage.h95
-rw-r--r--libetpan/src/driver/interface/maildriver.c383
-rw-r--r--libetpan/src/driver/interface/maildriver.h546
-rw-r--r--libetpan/src/driver/interface/maildriver_errors.h102
-rw-r--r--libetpan/src/driver/interface/maildriver_tools.c841
-rw-r--r--libetpan/src/driver/interface/maildriver_tools.h81
-rw-r--r--libetpan/src/driver/interface/maildriver_types.c340
-rw-r--r--libetpan/src/driver/interface/maildriver_types.h795
-rw-r--r--libetpan/src/driver/interface/maildriver_types_helper.c104
-rw-r--r--libetpan/src/driver/interface/maildriver_types_helper.h99
-rw-r--r--libetpan/src/driver/interface/mailfolder.c138
-rw-r--r--libetpan/src/driver/interface/mailfolder.h70
-rw-r--r--libetpan/src/driver/interface/mailmessage.c240
-rw-r--r--libetpan/src/driver/interface/mailmessage.h379
-rw-r--r--libetpan/src/driver/interface/mailmessage_tools.c600
-rw-r--r--libetpan/src/driver/interface/mailmessage_tools.h103
-rw-r--r--libetpan/src/driver/interface/mailmessage_types.c92
-rw-r--r--libetpan/src/driver/interface/mailmessage_types.h50
-rw-r--r--libetpan/src/driver/interface/mailstorage.c341
-rw-r--r--libetpan/src/driver/interface/mailstorage.h99
-rw-r--r--libetpan/src/driver/interface/mailstorage_tools.c372
-rw-r--r--libetpan/src/driver/interface/mailstorage_tools.h67
-rw-r--r--libetpan/src/driver/interface/mailstorage_types.h203
-rw-r--r--libetpan/src/driver/tools/generic_cache.c729
-rw-r--r--libetpan/src/driver/tools/generic_cache.h109
-rw-r--r--libetpan/src/driver/tools/generic_cache_types.h56
-rw-r--r--libetpan/src/driver/tools/imfcache.c1429
-rw-r--r--libetpan/src/driver/tools/imfcache.h75
-rw-r--r--libetpan/src/driver/tools/mailthread.c1742
-rw-r--r--libetpan/src/driver/tools/mailthread.h108
-rw-r--r--libetpan/src/driver/tools/mailthread_types.c90
-rw-r--r--libetpan/src/driver/tools/mailthread_types.h64
-rw-r--r--libetpan/src/engine/mailengine.c1636
-rw-r--r--libetpan/src/engine/mailengine.h190
-rw-r--r--libetpan/src/engine/mailprivacy.c949
-rw-r--r--libetpan/src/engine/mailprivacy.h117
-rw-r--r--libetpan/src/engine/mailprivacy_gnupg.c2614
-rw-r--r--libetpan/src/engine/mailprivacy_gnupg.h46
-rw-r--r--libetpan/src/engine/mailprivacy_smime.c1755
-rw-r--r--libetpan/src/engine/mailprivacy_smime.h84
-rw-r--r--libetpan/src/engine/mailprivacy_tools.c1283
-rw-r--r--libetpan/src/engine/mailprivacy_tools.h102
-rw-r--r--libetpan/src/engine/mailprivacy_types.h82
-rw-r--r--libetpan/src/low-level/imap/TODO4
-rw-r--r--libetpan/src/low-level/imap/mailimap.c2164
-rw-r--r--libetpan/src/low-level/imap/mailimap.h598
-rw-r--r--libetpan/src/low-level/imap/mailimap_helper.c205
-rw-r--r--libetpan/src/low-level/imap/mailimap_helper.h66
-rw-r--r--libetpan/src/low-level/imap/mailimap_keywords.c353
-rw-r--r--libetpan/src/low-level/imap/mailimap_keywords.h107
-rw-r--r--libetpan/src/low-level/imap/mailimap_parser.c9506
-rw-r--r--libetpan/src/low-level/imap/mailimap_parser.h69
-rw-r--r--libetpan/src/low-level/imap/mailimap_print.c1615
-rw-r--r--libetpan/src/low-level/imap/mailimap_print.h54
-rw-r--r--libetpan/src/low-level/imap/mailimap_sender.c2742
-rw-r--r--libetpan/src/low-level/imap/mailimap_sender.h164
-rw-r--r--libetpan/src/low-level/imap/mailimap_socket.c73
-rw-r--r--libetpan/src/low-level/imap/mailimap_socket.h54
-rw-r--r--libetpan/src/low-level/imap/mailimap_ssl.c73
-rw-r--r--libetpan/src/low-level/imap/mailimap_ssl.h54
-rw-r--r--libetpan/src/low-level/imap/mailimap_types.c2961
-rw-r--r--libetpan/src/low-level/imap/mailimap_types.h3274
-rw-r--r--libetpan/src/low-level/imap/mailimap_types_helper.c1269
-rw-r--r--libetpan/src/low-level/imap/mailimap_types_helper.h758
-rw-r--r--libetpan/src/low-level/imf/TODO12
-rw-r--r--libetpan/src/low-level/imf/mailimf.c7585
-rw-r--r--libetpan/src/low-level/imf/mailimf.h347
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.c868
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.h793
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.c1636
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.h370
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.c2021
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.h134
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.c149
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.h169
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.c2028
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.h142
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.c98
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.h135
-rw-r--r--libetpan/src/low-level/maildir/maildir.c798
-rw-r--r--libetpan/src/low-level/maildir/maildir.h67
-rw-r--r--libetpan/src/low-level/maildir/maildir_types.h91
-rw-r--r--libetpan/src/low-level/mbox/TODO0
-rw-r--r--libetpan/src/low-level/mbox/mailmbox.c1525
-rw-r--r--libetpan/src/low-level/mbox/mailmbox.h144
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_parse.c620
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_parse.h56
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_types.c251
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_types.h143
-rw-r--r--libetpan/src/low-level/mh/mailmh.c989
-rw-r--r--libetpan/src/low-level/mh/mailmh.h152
-rw-r--r--libetpan/src/low-level/mime/TODO10
-rw-r--r--libetpan/src/low-level/mime/mailmime.c1408
-rw-r--r--libetpan/src/low-level/mime/mailmime.h102
-rw-r--r--libetpan/src/low-level/mime/mailmime_content.c2381
-rw-r--r--libetpan/src/low-level/mime/mailmime_content.h89
-rw-r--r--libetpan/src/low-level/mime/mailmime_decode.c544
-rw-r--r--libetpan/src/low-level/mime/mailmime_decode.h55
-rw-r--r--libetpan/src/low-level/mime/mailmime_disposition.c595
-rw-r--r--libetpan/src/low-level/mime/mailmime_disposition.h62
-rw-r--r--libetpan/src/low-level/mime/mailmime_types.c753
-rw-r--r--libetpan/src/low-level/mime/mailmime_types.h440
-rw-r--r--libetpan/src/low-level/mime/mailmime_types_helper.c1385
-rw-r--r--libetpan/src/low-level/mime/mailmime_types_helper.h165
-rw-r--r--libetpan/src/low-level/mime/mailmime_write.c1416
-rw-r--r--libetpan/src/low-level/mime/mailmime_write.h73
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_file.c156
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_file.h105
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_generic.c1416
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_generic.h73
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_mem.c106
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_mem.h73
-rw-r--r--libetpan/src/low-level/nntp/newsnntp.c2486
-rw-r--r--libetpan/src/low-level/nntp/newsnntp.h187
-rw-r--r--libetpan/src/low-level/nntp/newsnntp_socket.c74
-rw-r--r--libetpan/src/low-level/nntp/newsnntp_socket.h55
-rw-r--r--libetpan/src/low-level/nntp/newsnntp_ssl.c73
-rw-r--r--libetpan/src/low-level/nntp/newsnntp_ssl.h55
-rw-r--r--libetpan/src/low-level/nntp/newsnntp_types.h144
-rw-r--r--libetpan/src/low-level/pop3/mailpop3.c1230
-rw-r--r--libetpan/src/low-level/pop3/mailpop3.h101
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_helper.c78
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_helper.h64
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_socket.c73
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_socket.h54
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_ssl.c73
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_ssl.h54
-rw-r--r--libetpan/src/low-level/pop3/mailpop3_types.h107
-rw-r--r--libetpan/src/low-level/smtp/TODO1
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp.c984
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp.h94
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_helper.c228
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_helper.h74
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_socket.c99
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_socket.h56
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_ssl.c74
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_ssl.h55
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_types.h126
-rw-r--r--libetpan/src/main/libetpan.h119
-rw-r--r--libetpan/src/main/libetpan_version.c53
-rw-r--r--libetpan/src/main/libetpan_version.h57
-rw-r--r--libetpan/src/main/libetpan_version.h.in57
397 files changed, 140378 insertions, 0 deletions
diff --git a/libetpan/COPYRIGHT b/libetpan/COPYRIGHT
new file mode 100644
index 0000000..88e0e03
--- a/dev/null
+++ b/libetpan/COPYRIGHT
@@ -0,0 +1,28 @@
1libEtPan! -- a mail stuff library
2
3Copyright (C) 2001, 2002 - DINH Viet Hoa
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions
8are met:
91. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
112. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
143. Neither the name of the libEtPan! project nor the names of its
15 contributors may be used to endorse or promote products derived
16 from this software without specific prior written permission.
17
18THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28SUCH DAMAGE.
diff --git a/libetpan/config.h b/libetpan/config.h
new file mode 100644
index 0000000..e8d3012
--- a/dev/null
+++ b/libetpan/config.h
@@ -0,0 +1,119 @@
1/* config.h. Generated by configure. */
2/* config.h.in. Generated from configure.in by autoheader. */
3
4/* Define to detected Berkeley DB major version number */
5#define DBVERS 0
6
7/* Define to 1 if you have the <ctype.h> header file. */
8#define HAVE_CTYPE_H 1
9
10/* Define to 1 if you have the <dlfcn.h> header file. */
11#define HAVE_DLFCN_H 1
12
13/* Define to 1 if you have the <fcntl.h> header file. */
14#define HAVE_FCNTL_H 1
15
16/* Define to 1 if you have the `getpagesize' function. */
17#define HAVE_GETPAGESIZE 1
18
19/* Define if you have the iconv() function. */
20#define HAVE_ICONV 1
21
22/* prototype of iconv() has const parameters */
23/* #undef HAVE_ICONV_PROTO_CONST */
24
25/* Define to 1 if you have the <inttypes.h> header file. */
26#define HAVE_INTTYPES_H 1
27
28/* Define to 1 if you have the `lockfile' library (-llockfile). */
29/* #undef HAVE_LIBLOCKFILE */
30
31/* Define to 1 if you have the `nsl' library (-lnsl). */
32/* #undef HAVE_LIBNSL */
33
34/* Define to 1 if you have the `socket' library (-lsocket). */
35/* #undef HAVE_LIBSOCKET */
36
37/* Define to 1 if you have the <limits.h> header file. */
38#define HAVE_LIMITS_H 1
39
40/* Define to 1 if you have the <memory.h> header file. */
41#define HAVE_MEMORY_H 1
42
43/* Define to 1 if you have a working `mmap' system call. */
44#define HAVE_MMAP 1
45
46/* Define to 1 if you have the <netdb.h> header file. */
47#define HAVE_NETDB_H 1
48
49/* Define to 1 if you have the <netinet/in.h> header file. */
50#define HAVE_NETINET_IN_H 1
51
52/* Define to 1 if you have the <pthread.h> header file. */
53#define HAVE_PTHREAD_H 1
54
55/* Define to 1 if you have the <stdint.h> header file. */
56#define HAVE_STDINT_H 1
57
58/* Define to 1 if you have the <stdlib.h> header file. */
59#define HAVE_STDLIB_H 1
60
61/* Define to 1 if you have the <strings.h> header file. */
62#define HAVE_STRINGS_H 1
63
64/* Define to 1 if you have the <string.h> header file. */
65#define HAVE_STRING_H 1
66
67/* Define to 1 if you have the <sys/mman.h> header file. */
68#define HAVE_SYS_MMAN_H 1
69
70/* Define to 1 if you have the <sys/param.h> header file. */
71#define HAVE_SYS_PARAM_H 1
72
73/* Define to 1 if you have the <sys/socket.h> header file. */
74#define HAVE_SYS_SOCKET_H 1
75
76/* Define to 1 if you have the <sys/stat.h> header file. */
77#define HAVE_SYS_STAT_H 1
78
79/* Define to 1 if you have the <sys/types.h> header file. */
80#define HAVE_SYS_TYPES_H 1
81
82/* Define to 1 if you have the <unistd.h> header file. */
83#define HAVE_UNISTD_H 1
84
85/* Define to include multithreading support */
86#define LIBETPAN_REENTRANT 1
87
88/* Define this to the version of libEtPan */
89#define LIBETPAN_VERSION "0.36"
90
91/* Define this to the major version of libEtPan */
92#define LIBETPAN_VERSION_MAJOR 0
93
94/* Define this to the minor version of libEtPan */
95#define LIBETPAN_VERSION_MINOR 36
96
97/* Define to the address where bug reports for this package should be sent. */
98#define PACKAGE_BUGREPORT ""
99
100/* Define to the full name of this package. */
101#define PACKAGE_NAME ""
102
103/* Define to the full name and version of this package. */
104#define PACKAGE_STRING ""
105
106/* Define to the one symbol short name of this package. */
107#define PACKAGE_TARNAME ""
108
109/* Define to the version of this package. */
110#define PACKAGE_VERSION ""
111
112/* Define to 1 if you have the ANSI C header files. */
113#define STDC_HEADERS 1
114
115/* Define to be lazy on protocol syntax */
116#define UNSTRICT_SYNTAX 1
117
118/* Define to use OpenSSL */
119#define USE_SSL 1
diff --git a/libetpan/include/libetpan/carray.h b/libetpan/include/libetpan/carray.h
new file mode 100644
index 0000000..f906c57
--- a/dev/null
+++ b/libetpan/include/libetpan/carray.h
@@ -0,0 +1,123 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * carray - Implements simple dynamic pointer arrays
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CARRAY_H
40#define CARRAY_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46struct carray_s {
47 void ** array;
48 unsigned int len;
49 unsigned int max;
50};
51
52typedef struct carray_s carray;
53
54/* Creates a new array of pointers, with initsize preallocated cells */
55carray * carray_new(unsigned int initsize);
56
57/* Adds the pointer to data in the array.
58 Returns the index of the pointer in the array or -1 on error */
59int carray_add(carray * array, void * data, unsigned int * index);
60
61int carray_set_size(carray * array, unsigned int new_size);
62
63/* Removes the cell at this index position. Returns TRUE on success.
64 Order of elements in the array IS changed. */
65int carray_delete(carray * array, unsigned int indx);
66
67/* Removes the cell at this index position. Returns TRUE on success.
68 Order of elements in the array IS not changed. */
69int carray_delete_slow(carray * array, unsigned int indx);
70
71/* remove without decreasing the size of the array */
72int carray_delete_fast(carray * array, unsigned int indx);
73
74/* Some of the following routines can be implemented as macros to
75 be faster. If you don't want it, define NO_MACROS */
76#ifdef NO_MACROS
77
78/* Returns the array itself */
79void ** carray_data(carray *);
80
81/* Returns the number of elements in the array */
82int carray_count(carray *);
83
84/* Returns the contents of one cell */
85void * carray_get(carray * array, unsigned int indx);
86
87/* Sets the contents of one cell */
88void carray_set(carray * array, unsigned int indx, void * value);
89
90#else
91
92#if 0
93#define carray_data(a) (a->array)
94#define carray_count(a) (a->len)
95#define carray_get(a, indx) (a->array[indx])
96#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0)
97#endif
98
99static inline void ** carray_data(carray * array) {
100 return array->array;
101}
102
103static inline unsigned int carray_count(carray * array) {
104 return array->len;
105}
106
107static inline void * carray_get(carray * array, unsigned int indx) {
108 return array->array[indx];
109}
110
111static inline void carray_set(carray * array,
112 unsigned int indx, void * value) {
113 array->array[indx] = value;
114}
115#endif
116
117void carray_free(carray * array);
118
119#ifdef __cplusplus
120}
121#endif
122
123#endif
diff --git a/libetpan/include/libetpan/charconv.h b/libetpan/include/libetpan/charconv.h
new file mode 100644
index 0000000..8a68f7b
--- a/dev/null
+++ b/libetpan/include/libetpan/charconv.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef CHARCONV_H
37
38#define CHARCONV_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45
46enum {
47 MAIL_CHARCONV_NO_ERROR = 0,
48 MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET,
49 MAIL_CHARCONV_ERROR_MEMORY,
50 MAIL_CHARCONV_ERROR_CONV,
51};
52
53int charconv(const char * tocode, const char * fromcode,
54 const char * str, size_t length,
55 char ** result);
56
57int charconv_buffer(const char * tocode, const char * fromcode,
58 const char * str, size_t length,
59 char ** result, size_t * result_len);
60
61void charconv_buffer_free(char * str);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/include/libetpan/chash.h b/libetpan/include/libetpan/chash.h
new file mode 100644
index 0000000..a9a61e5
--- a/dev/null
+++ b/libetpan/include/libetpan/chash.h
@@ -0,0 +1,165 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * chash - Implements generic hash tables.
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CHASH_H
40#define CHASH_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46typedef struct {
47 void * data;
48 unsigned int len;
49} chashdatum;
50
51struct chash {
52 unsigned int size;
53 unsigned int count;
54 int copyvalue;
55 int copykey;
56 struct chashcell ** cells;
57};
58
59typedef struct chash chash;
60
61struct chashcell {
62 unsigned int func;
63 chashdatum key;
64 chashdatum value;
65 struct chashcell * next;
66};
67
68typedef struct chashcell chashiter;
69
70#define CHASH_COPYNONE 0
71#define CHASH_COPYKEY 1
72#define CHASH_COPYVALUE 2
73#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE)
74
75#define CHASH_DEFAULTSIZE 13
76
77/* Allocates a new (empty) hash using this initial size and the given flags,
78 specifying which data should be copied in the hash.
79 CHASH_COPYNONE : Keys/Values are not copied.
80 CHASH_COPYKEY : Keys are dupped and freed as needed in the hash.
81 CHASH_COPYVALUE : Values are dupped and freed as needed in the hash.
82 CHASH_COPYALL : Both keys and values are dupped in the hash.
83 */
84chash * chash_new(unsigned int size, int flags);
85
86/* Frees a hash */
87void chash_free(chash * hash);
88
89/* Removes all elements from a hash */
90void chash_clear(chash * hash);
91
92/* Adds an entry in the hash table.
93 Length can be 0 if key/value are strings.
94 If an entry already exists for this key, it is replaced, and its value
95 is returned. Otherwise, the data pointer will be NULL and the length
96 field be set to TRUE or FALSe to indicate success or failure. */
97int chash_set(chash * hash,
98 chashdatum * key,
99 chashdatum * value,
100 chashdatum * oldvalue);
101
102/* Retrieves the data associated to the key if it is found in the hash table.
103 The data pointer and the length will be NULL if not found*/
104int chash_get(chash * hash,
105 chashdatum * key, chashdatum * result);
106
107/* Removes the entry associated to this key if it is found in the hash table,
108 and returns its contents if not dupped (otherwise, pointer will be NULL
109 and len TRUE). If entry is not found both pointer and len will be NULL. */
110int chash_delete(chash * hash,
111 chashdatum * key,
112 chashdatum * oldvalue);
113
114/* Resizes the hash table to the passed size. */
115int chash_resize(chash * hash, unsigned int size);
116
117/* Returns an iterator to the first non-empty entry of the hash table */
118chashiter * chash_begin(chash * hash);
119
120/* Returns the next non-empty entry of the hash table */
121chashiter * chash_next(chash * hash, chashiter * iter);
122
123/* Some of the following routines can be implemented as macros to
124 be faster. If you don't want it, define NO_MACROS */
125#ifdef NO_MACROS
126/* Returns the size of the hash table */
127unsigned int chash_size(chash * hash);
128
129/* Returns the number of entries in the hash table */
130unsigned int chash_count(chash * hash);
131
132/* Returns the key part of the entry pointed by the iterator */
133void chash_key(chashiter * iter, chashdatum * result);
134
135/* Returns the value part of the entry pointed by the iterator */
136void chash_value(chashiter * iter, chashdatum * result);
137
138#else
139static inline unsigned int chash_size(chash * hash)
140{
141 return hash->size;
142}
143
144static inline unsigned int chash_count(chash * hash)
145{
146 return hash->count;
147}
148
149static inline void chash_key(chashiter * iter, chashdatum * result)
150{
151 * result = iter->key;
152}
153
154static inline void chash_value(chashiter * iter, chashdatum * result)
155{
156 * result = iter->value;
157}
158
159#endif
160
161#ifdef __cplusplus
162}
163#endif
164
165#endif
diff --git a/libetpan/include/libetpan/cinthash.h b/libetpan/include/libetpan/cinthash.h
new file mode 100644
index 0000000..7103d4f
--- a/dev/null
+++ b/libetpan/include/libetpan/cinthash.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef CINTHASH_H
37
38#define CINTHASH_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44typedef struct cinthash_t {
45 struct cinthash_list * table;
46 unsigned long hashtable_size ;
47 unsigned long count;
48} cinthash_t;
49
50cinthash_t * cinthash_new(unsigned long hashtable_size);
51void cinthash_free(cinthash_t * table);
52
53int cinthash_add(cinthash_t * table, unsigned long hash, void * data);
54int cinthash_remove(cinthash_t * table, unsigned long hash);
55void * cinthash_find(cinthash_t * table, unsigned long hash);
56
57void cinthash_foreach_key(cinthash_t * table,
58 void (* func)(unsigned long, void *),
59 void * data);
60
61void cinthash_foreach_data(cinthash_t * table,
62 void (* fun)(void *, void *),
63 void * data);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/include/libetpan/clist.h b/libetpan/include/libetpan/clist.h
new file mode 100644
index 0000000..0daf1ed
--- a/dev/null
+++ b/libetpan/include/libetpan/clist.h
@@ -0,0 +1,133 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * clist - Implements simple generic double-linked pointer lists
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CLIST_H
40#define CLIST_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46typedef struct clistcell_s {
47 void * data;
48 struct clistcell_s * previous;
49 struct clistcell_s * next;
50} clistcell;
51
52struct clist_s {
53 clistcell * first;
54 clistcell * last;
55 int count;
56};
57
58typedef struct clist_s clist;
59typedef clistcell clistiter;
60
61/* Allocate a new pointer list */
62clist * clist_new();
63
64/* Destroys a list. Data pointed by data pointers is NOT freed. */
65void clist_free(clist *);
66
67/* Some of the following routines can be implemented as macros to
68 be faster. If you don't want it, define NO_MACROS */
69#ifdef NO_MACROS
70
71/* Returns TRUE if list is empty */
72int clist_isempty(clist *);
73
74/* Returns the number of elements in the list */
75int clist_count(clist *);
76
77/* Returns an iterator to the first element of the list */
78clistiter * clist_begin(clist *);
79
80/* Returns an iterator to the last element of the list */
81clistiter * clist_end(clist *);
82
83/* Returns an iterator to the next element of the list */
84clistiter * clist_next(clistiter *);
85
86/* Returns an iterator to the previous element of the list */
87clistiter * clist_previous(clistiter *);
88
89/* Returns the data pointer of this element of the list */
90void* clist_content(clistiter *);
91
92/* Inserts this data pointer at the beginning of the list */
93int clist_prepend(clist *, void *);
94
95/* Inserts this data pointer at the end of the list */
96int clist_append(clist *, void *);
97#else
98#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL))
99#define clist_count(lst) (lst->count)
100#define clist_begin(lst) (lst->first)
101#define clist_end(lst) (lst->last)
102#define clist_next(iter) (iter ? iter->next : NULL)
103#define clist_previous(iter) (iter ? iter->previous : NULL)
104#define clist_content(iter) (iter ? iter->data : NULL)
105#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data))
106#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data))
107#endif
108
109/* Inserts this data pointer before the element pointed by the iterator */
110int clist_insert_before(clist *, clistiter *, void *);
111
112/* Inserts this data pointer after the element pointed by the iterator */
113int clist_insert_after(clist *, clistiter *, void *);
114
115/* Deletes the element pointed by the iterator.
116 Returns an iterator to the next element. */
117clistiter * clist_delete(clist *, clistiter *);
118
119typedef void (* clist_func)(void *, void *);
120
121void clist_foreach(clist * lst, clist_func func, void * data);
122
123void clist_concat(clist * dest, clist * src);
124
125void * clist_nth_data(clist * lst, int index);
126
127clistiter * clist_nth(clist * lst, int index);
128
129#ifdef __cplusplus
130}
131#endif
132
133#endif
diff --git a/libetpan/include/libetpan/data_message_driver.h b/libetpan/include/libetpan/data_message_driver.h
new file mode 100644
index 0000000..b6569c2
--- a/dev/null
+++ b/libetpan/include/libetpan/data_message_driver.h
@@ -0,0 +1,50 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DATA_MESSAGE_DRIVER_H
37
38#define DATA_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_DATA_MESSAGE
43
44extern mailmessage_driver * data_message_driver;
45
46mailmessage * data_message_init(char * data, size_t len);
47
48void data_message_detach_mime(mailmessage * msg);
49
50#endif
diff --git a/libetpan/include/libetpan/dbdriver.h b/libetpan/include/libetpan/dbdriver.h
new file mode 100644
index 0000000..1c2a96d
--- a/dev/null
+++ b/libetpan/include/libetpan/dbdriver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_H
37
38#define DBDRIVER_H
39
40#include <libetpan/dbdriver_message.h>
41#include <libetpan/dbdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * db_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/include/libetpan/dbdriver_message.h b/libetpan/include/libetpan/dbdriver_message.h
new file mode 100644
index 0000000..f634775
--- a/dev/null
+++ b/libetpan/include/libetpan/dbdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_MESSAGE_H
37
38#define DBDRIVER_MESSAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * db_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/dbdriver_types.h b/libetpan/include/libetpan/dbdriver_types.h
new file mode 100644
index 0000000..052e3db
--- a/dev/null
+++ b/libetpan/include/libetpan/dbdriver_types.h
@@ -0,0 +1,71 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_TYPES_H
37
38#define DBDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/generic_cache_types.h>
44#include <libetpan/mailstorage_types.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50struct db_session_state_data {
51 char db_filename[PATH_MAX];
52 struct mail_flags_store * db_flags_store;
53};
54
55/* db storage */
56
57/*
58 db_mailstorage is the state data specific to the db storage.
59
60 - pathname is the path of the db storage.
61*/
62
63struct db_mailstorage {
64 char * db_pathname;
65};
66
67#ifdef __cplusplus
68}
69#endif
70
71#endif
diff --git a/libetpan/include/libetpan/dbstorage.h b/libetpan/include/libetpan/dbstorage.h
new file mode 100644
index 0000000..5fa9659
--- a/dev/null
+++ b/libetpan/include/libetpan/dbstorage.h
@@ -0,0 +1,61 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBSTORAGE_H
37
38#define DBSTORAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 db_mailstorage_init is the constructor for a DB storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52*/
53
54int db_mailstorage_init(struct mailstorage * storage,
55 char * db_pathname);
56
57#ifdef __cplusplus
58}
59#endif
60
61#endif
diff --git a/libetpan/include/libetpan/generic_cache_types.h b/libetpan/include/libetpan/generic_cache_types.h
new file mode 100644
index 0000000..bc69b3c
--- a/dev/null
+++ b/libetpan/include/libetpan/generic_cache_types.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef GENERIC_CACHE_TYPE_H
37
38#define GENERIC_CACHE_TYPE_H
39
40#include <libetpan/carray.h>
41#include <libetpan/chash.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47struct mail_flags_store {
48 carray * fls_tab;
49 chash * fls_hash;
50};
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/include/libetpan/hotmailstorage.h b/libetpan/include/libetpan/hotmailstorage.h
new file mode 100644
index 0000000..05d6385
--- a/dev/null
+++ b/libetpan/include/libetpan/hotmailstorage.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef HOTMAILSTORAGE_H
37
38#define HOTMAILSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstorage_types.h"
45
46int hotmail_mailstorage_init(struct mailstorage * storage,
47 char * hotmail_login, char * hotmail_password,
48 int hotmail_cached, char * hotmail_cache_directory,
49 char * hotmail_flags_directory);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
56
diff --git a/libetpan/include/libetpan/imapdriver.h b/libetpan/include/libetpan/imapdriver.h
new file mode 100644
index 0000000..cbc0c51
--- a/dev/null
+++ b/libetpan/include/libetpan/imapdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_H
37
38#define IMAPDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46extern mailsession_driver * imap_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/imapdriver_cached.h b/libetpan/include/libetpan/imapdriver_cached.h
new file mode 100644
index 0000000..c324f5e
--- a/dev/null
+++ b/libetpan/include/libetpan/imapdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_H
37
38#define IMAPDRIVER_CACHED_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * imap_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/imapdriver_cached_message.h b/libetpan/include/libetpan/imapdriver_cached_message.h
new file mode 100644
index 0000000..bf43311
--- a/dev/null
+++ b/libetpan/include/libetpan/imapdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_MESSAGE_H
37
38#define IMAPDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/imapdriver_message.h b/libetpan/include/libetpan/imapdriver_message.h
new file mode 100644
index 0000000..74fc2e6
--- a/dev/null
+++ b/libetpan/include/libetpan/imapdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_MESSAGE_H
37
38#define IMAPDRIVER_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/imapdriver_types.h b/libetpan/include/libetpan/imapdriver_types.h
new file mode 100644
index 0000000..00559dc
--- a/dev/null
+++ b/libetpan/include/libetpan/imapdriver_types.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TYPES_H
37
38#define IMAPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mailimap.h>
43#include <libetpan/maildriver_types.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/* IMAP driver for session */
52
53struct imap_session_state_data {
54 mailimap * imap_session;
55 char * imap_mailbox;
56 struct mail_flags_store * imap_flags_store;
57};
58
59enum {
60 IMAP_SECTION_MESSAGE,
61 IMAP_SECTION_HEADER,
62 IMAP_SECTION_MIME,
63 IMAP_SECTION_BODY
64};
65
66/* cached IMAP driver for session */
67
68enum {
69 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
70};
71
72struct imap_cached_session_state_data {
73 mailsession * imap_ancestor;
74 char * imap_quoted_mb;
75 char imap_cache_directory[PATH_MAX];
76 carray * imap_uid_list;
77};
78
79
80/* IMAP storage */
81
82/*
83 imap_mailstorage is the state data specific to the IMAP4rev1 storage.
84
85 - servername this is the name of the IMAP4rev1 server
86
87 - port is the port to connect to, on the server.
88 you give 0 to use the default port.
89
90 - command, if non-NULL the command used to connect to the
91 server instead of allowing normal TCP connections to be used.
92
93 - connection_type is the type of socket layer to use.
94 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
95 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or
96 CONNECTION_TYPE_COMMAND.
97
98 - auth_type is the authenticate mechanism to use.
99 The value can be IMAP_AUTH_TYPE_PLAIN.
100 Other values are not yet implemented.
101
102 - login is the login of the IMAP4rev1 account.
103
104 - password is the password of the IMAP4rev1 account.
105
106 - cached if this value is != 0, a persistant cache will be
107 stored on local system.
108
109 - cache_directory is the location of the cache
110*/
111
112struct imap_mailstorage {
113 char * imap_servername;
114 uint16_t imap_port;
115 char * imap_command;
116 int imap_connection_type;
117
118 int imap_auth_type;
119 char * imap_login;
120 char * imap_password;
121
122 int imap_cached;
123 char * imap_cache_directory;
124};
125
126/* this is the type of IMAP4rev1 authentication */
127
128enum {
129 IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */
130 IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
131 IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
132 IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
133 IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
134 IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
135 IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
136 IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
137};
138
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/include/libetpan/imapstorage.h b/libetpan/include/libetpan/imapstorage.h
new file mode 100644
index 0000000..929a86e
--- a/dev/null
+++ b/libetpan/include/libetpan/imapstorage.h
@@ -0,0 +1,90 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPSTORAGE_H
37
38#define IMAPSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46/*
47 imap_mailstorage_init is the constructor for a IMAP4rev1 storage
48
49 @param storage this is the storage to initialize.
50
51 @param servername this is the name of the IMAP4rev1 server
52
53 @param port is the port to connect to, on the server.
54 you give 0 to use the default port.
55
56 @param command the command used to connect to the server instead of
57 allowing normal TCP connections to be used.
58
59 @param connection_type is the type of socket layer to use.
60 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
61 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
62 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
63 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
64
65 @param auth_type is the authenticate mechanism to use.
66 The value can be IMAP_AUTH_TYPE_PLAIN.
67 Other values are not yet implemented.
68
69 @param login is the login of the IMAP4rev1 account.
70
71 @param password is the password of the IMAP4rev1 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77*/
78
79int imap_mailstorage_init(struct mailstorage * storage,
80 char * imap_servername, uint16_t imap_port,
81 char * imap_command,
82 int imap_connection_type, int imap_auth_type,
83 char * imap_login, char * imap_password,
84 int imap_cached, char * imap_cache_directory);
85
86#ifdef __cplusplus
87}
88#endif
89
90#endif
diff --git a/libetpan/include/libetpan/libetpan-config.h b/libetpan/include/libetpan/libetpan-config.h
new file mode 100644
index 0000000..20d1e62
--- a/dev/null
+++ b/libetpan/include/libetpan/libetpan-config.h
@@ -0,0 +1,7 @@
1#ifndef LIBETPAN_CONFIG_H
2#define LIBETPAN_CONFIG_H
3#include <limits.h>
4#include <sys/param.h>
5#define MAIL_DIR_SEPARATOR '/'
6#define MAIL_DIR_SEPARATOR_S "/"
7#endif
diff --git a/libetpan/include/libetpan/libetpan.h b/libetpan/include/libetpan/libetpan.h
new file mode 100644
index 0000000..c58bede
--- a/dev/null
+++ b/libetpan/include/libetpan/libetpan.h
@@ -0,0 +1,119 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef LIBETPAN_H
37
38#define LIBETPAN_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/libetpan_version.h>
45#include <libetpan/maildriver.h>
46#include <libetpan/mailmessage.h>
47#include <libetpan/mailfolder.h>
48#include <libetpan/mailstorage.h>
49#include <libetpan/mailthread.h>
50#include <libetpan/mailsmtp.h>
51#include <libetpan/charconv.h>
52
53/* mbox driver */
54#include <libetpan/mboxdriver.h>
55#include <libetpan/mboxdriver_message.h>
56#include <libetpan/mboxdriver_cached.h>
57#include <libetpan/mboxdriver_cached_message.h>
58#include <libetpan/mboxstorage.h>
59
60/* MH driver */
61#include <libetpan/mhdriver.h>
62#include <libetpan/mhdriver_message.h>
63#include <libetpan/mhdriver_cached.h>
64#include <libetpan/mhdriver_cached_message.h>
65#include <libetpan/mhstorage.h>
66
67/* IMAP4rev1 driver */
68#include <libetpan/imapdriver.h>
69#include <libetpan/imapdriver_message.h>
70#include <libetpan/imapdriver_cached.h>
71#include <libetpan/imapdriver_cached_message.h>
72#include <libetpan/imapstorage.h>
73
74/* POP3 driver */
75#include <libetpan/pop3driver.h>
76#include <libetpan/pop3driver_message.h>
77#include <libetpan/pop3driver_cached.h>
78#include <libetpan/pop3driver_cached_message.h>
79#include <libetpan/pop3storage.h>
80
81/* Hotmail */
82#include <libetpan/hotmailstorage.h>
83
84/* NNTP driver */
85#include <libetpan/nntpdriver.h>
86#include <libetpan/nntpdriver_message.h>
87#include <libetpan/nntpdriver_cached.h>
88#include <libetpan/nntpdriver_cached_message.h>
89#include <libetpan/nntpstorage.h>
90
91/* maildir driver */
92#include <libetpan/maildirdriver.h>
93#include <libetpan/maildirdriver_message.h>
94#include <libetpan/maildirdriver_cached.h>
95#include <libetpan/maildirdriver_cached_message.h>
96#include <libetpan/maildirstorage.h>
97
98/* db driver */
99#include <libetpan/dbdriver.h>
100#include <libetpan/dbdriver_message.h>
101#include <libetpan/dbstorage.h>
102
103/* message which content is given by a MIME structure */
104#include <libetpan/mime_message_driver.h>
105
106/* message which content given by a string */
107#include <libetpan/data_message_driver.h>
108
109/* engine */
110#include <libetpan/mailprivacy.h>
111#include <libetpan/mailengine.h>
112#include <libetpan/mailprivacy_gnupg.h>
113#include <libetpan/mailprivacy_smime.h>
114
115#ifdef __cplusplus
116}
117#endif
118
119#endif
diff --git a/libetpan/include/libetpan/libetpan_version.h b/libetpan/include/libetpan/libetpan_version.h
new file mode 100644
index 0000000..c1737d1
--- a/dev/null
+++ b/libetpan/include/libetpan/libetpan_version.h
@@ -0,0 +1,57 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001 - 2003 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef LIBETPAN_VERSION_H
37
38#define LIBETPAN_VERSION_H
39
40#ifndef LIBETPAN_VERSION_MAJOR
41#define LIBETPAN_VERSION_MAJOR 0
42#endif
43
44#ifndef LIBETPAN_VERSION_MINOR
45#define LIBETPAN_VERSION_MINOR 36
46#endif
47
48#ifndef LIBETPAN_REENTRANT
49#if 1
50#define LIBETPAN_REENTRANT 1
51#endif
52#endif
53
54int libetpan_get_version_major(void);
55int libetpan_get_version_minor(void);
56
57#endif
diff --git a/libetpan/include/libetpan/mail.h b/libetpan/include/libetpan/mail.h
new file mode 100644
index 0000000..447aaf7
--- a/dev/null
+++ b/libetpan/include/libetpan/mail.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_H
37
38#define MAIL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/include/libetpan/maildir.h b/libetpan/include/libetpan/maildir.h
new file mode 100644
index 0000000..d099dc0
--- a/dev/null
+++ b/libetpan/include/libetpan/maildir.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIR_H
37
38#define MAILDIR_H
39
40#include <libetpan/maildir_types.h>
41
42struct maildir * maildir_new(const char * path);
43
44void maildir_free(struct maildir * md);
45
46int maildir_update(struct maildir * md);
47
48int maildir_message_add_uid(struct maildir * md,
49 const char * message, size_t size,
50 char * uid, size_t max_uid_len);
51
52int maildir_message_add(struct maildir * md,
53 const char * message, size_t size);
54
55int maildir_message_add_file_uid(struct maildir * md, int fd,
56 char * uid, size_t max_uid_len);
57
58int maildir_message_add_file(struct maildir * md, int fd);
59
60char * maildir_message_get(struct maildir * md, const char * uid);
61
62int maildir_message_remove(struct maildir * md, const char * uid);
63
64int maildir_message_change_flags(struct maildir * md,
65 const char * uid, int new_flags);
66
67#endif
diff --git a/libetpan/include/libetpan/maildir_types.h b/libetpan/include/libetpan/maildir_types.h
new file mode 100644
index 0000000..5be5a78
--- a/dev/null
+++ b/libetpan/include/libetpan/maildir_types.h
@@ -0,0 +1,91 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIR_TYPES_H
37
38#define MAILDIR_TYPES_H
39
40#include <sys/types.h>
41#include <unistd.h>
42#include <libetpan/chash.h>
43#include <libetpan/carray.h>
44#include <inttypes.h>
45
46#include <libetpan/libetpan-config.h>
47
48#define LIBETPAN_MAILDIR
49
50enum {
51 MAILDIR_NO_ERROR = 0,
52 MAILDIR_ERROR_CREATE,
53 MAILDIR_ERROR_DIRECTORY,
54 MAILDIR_ERROR_MEMORY,
55 MAILDIR_ERROR_FILE,
56 MAILDIR_ERROR_NOT_FOUND,
57 MAILDIR_ERROR_FOLDER,
58};
59
60#define MAILDIR_FLAG_NEW (1 << 0)
61#define MAILDIR_FLAG_SEEN (1 << 1)
62#define MAILDIR_FLAG_REPLIED (1 << 2)
63#define MAILDIR_FLAG_FLAGGED (1 << 3)
64#define MAILDIR_FLAG_TRASHED (1 << 4)
65
66struct maildir_msg {
67 char * msg_uid;
68 char * msg_filename;
69 int msg_flags;
70};
71
72/*
73 work around for missing #define HOST_NAME_MAX in Linux
74*/
75
76#ifndef HOST_NAME_MAX
77#define HOST_NAME_MAX 255
78#endif
79
80struct maildir {
81 pid_t mdir_pid;
82 char mdir_hostname[HOST_NAME_MAX];
83 char mdir_path[PATH_MAX];
84 uint32_t mdir_counter;
85 time_t mdir_mtime_new;
86 time_t mdir_mtime_cur;
87 carray * mdir_msg_list;
88 chash * mdir_msg_hash;
89};
90
91#endif
diff --git a/libetpan/include/libetpan/maildirdriver.h b/libetpan/include/libetpan/maildirdriver.h
new file mode 100644
index 0000000..0abe09d
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirdriver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_H
37
38#define MAILDIRDRIVER_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/include/libetpan/maildirdriver_cached.h b/libetpan/include/libetpan/maildirdriver_cached.h
new file mode 100644
index 0000000..5c3d8a9
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirdriver_cached.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_H
37
38#define MAILDIRDRIVER_CACHED_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_cached_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/include/libetpan/maildirdriver_cached_message.h b/libetpan/include/libetpan/maildirdriver_cached_message.h
new file mode 100644
index 0000000..b9e0215
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H
37
38#define MAILDIRDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/maildirdriver_message.h b/libetpan/include/libetpan/maildirdriver_message.h
new file mode 100644
index 0000000..ed0a4d1
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_MESSAGE_H
37
38#define MAILDIRDRIVER_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/maildirdriver_types.h b/libetpan/include/libetpan/maildirdriver_types.h
new file mode 100644
index 0000000..c965b3e
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirdriver_types.h
@@ -0,0 +1,96 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_TYPES_H
37
38#define MAILDIRDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/maildir.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51struct maildir_session_state_data {
52 struct maildir * md_session;
53 struct mail_flags_store * md_flags_store;
54};
55
56enum {
57 MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
58 MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
59};
60
61struct maildir_cached_session_state_data {
62 mailsession * md_ancestor;
63 char * md_quoted_mb;
64 struct mail_flags_store * md_flags_store;
65 char md_cache_directory[PATH_MAX];
66 char md_flags_directory[PATH_MAX];
67};
68
69/* maildir storage */
70
71/*
72 maildir_mailstorage is the state data specific to the maildir storage.
73
74 - pathname is the path of the maildir storage.
75
76 - cached if this value is != 0, a persistant cache will be
77 stored on local system.
78
79 - cache_directory is the location of the cache.
80
81 - flags_directory is the location of the flags.
82*/
83
84struct maildir_mailstorage {
85 char * md_pathname;
86
87 int md_cached;
88 char * md_cache_directory;
89 char * md_flags_directory;
90};
91
92#ifdef __cplusplus
93}
94#endif
95
96#endif
diff --git a/libetpan/include/libetpan/maildirstorage.h b/libetpan/include/libetpan/maildirstorage.h
new file mode 100644
index 0000000..0ad04b9
--- a/dev/null
+++ b/libetpan/include/libetpan/maildirstorage.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRSTORAGE_H
37
38#define MAILDIRSTORAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 maildir_mailstorage_init is the constructor for a maildir storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int maildir_mailstorage_init(struct mailstorage * storage,
62 char * md_pathname, int md_cached,
63 char * md_cache_directory, char * md_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/include/libetpan/maildriver.h b/libetpan/include/libetpan/maildriver.h
new file mode 100644
index 0000000..16e830b
--- a/dev/null
+++ b/libetpan/include/libetpan/maildriver.h
@@ -0,0 +1,546 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_H
37
38#define MAILDRIVER_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/maildriver_types_helper.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* mailsession */
48
49/*
50 mailsession_new creates a new session, using the given driver
51
52 @return the created session is returned
53*/
54
55mailsession * mailsession_new(mailsession_driver * sess_driver);
56
57/*
58 mailsession_free release the memory used by the session
59*/
60
61void mailsession_free(mailsession * session);
62
63/*
64 mailsession_parameters is used to make calls specific to the driver
65
66 @param id is the command to send to the driver,
67 usually, commands can be found in the header of the driver
68
69 @param value is the parameter of the specific call
70
71 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
72 on error
73*/
74
75int mailsession_parameters(mailsession * session,
76 int id, void * value);
77
78/*
79 There are drivers of two kinds : stream drivers (driver that connects
80 to servers through TCP or other means of connection) and file drivers
81 (driver that are based on filesystem)
82
83 The following function can only be used by stream drivers.
84 mailsession_connect_stream connects a stream to the session
85
86 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
87 on error
88*/
89
90int mailsession_connect_stream(mailsession * session, mailstream * s);
91
92/*
93 The following function can only be used by file drivers.
94 mailsession_connect_path selects the main path of the session
95
96 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
97 on error
98*/
99
100int mailsession_connect_path(mailsession * session, char * path);
101
102/*
103 NOTE: works only on stream drivers
104
105 mailsession_starttls switches the current connection to TLS (secure layer)
106
107 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
108 on error
109*/
110
111int mailsession_starttls(mailsession * session);
112
113/*
114 mailsession_login notifies the login and the password to authenticate
115 to the session
116
117 @param userid the given string is only needed at this function call
118 (it will be duplicated if necessary)
119 @param password the given string is only needed at this function call
120 (it will be duplicated if necessary)
121
122 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
123 on error
124*/
125
126int mailsession_login(mailsession * session,
127 char * userid, char * password);
128
129/*
130 NOTE: this function doesn't often work on filsystem drivers
131
132 mailsession_logout deconnects the session and closes the stream.
133
134 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
135 on error
136*/
137
138int mailsession_logout(mailsession * session);
139
140/*
141 mailsession_noop does no operation on the session, but it can be
142 used to poll for the status of the connection.
143
144 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
145 on error
146*/
147
148int mailsession_noop(mailsession * session);
149
150/*
151 NOTE: driver's specific should be used
152
153 mailsession_build_folder_name will return an allocated string with
154 that contains the complete path of the folder to create
155
156 @param session the sesion
157 @param mb is the parent mailbox
158 @param name is the name of the folder to create
159 @param result the complete path of the folder to create will be
160 stored in (* result), this name have to be freed with free()
161
162 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
163 on error
164*/
165
166int mailsession_build_folder_name(mailsession * session, char * mb,
167 char * name, char ** result);
168
169/*
170 NOTE: driver's specific should be used
171
172 mailsession_create_folder creates the folder that corresponds to the
173 given name
174
175 @param session the session
176 @param mb is the name of the mailbox
177
178 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
179 on error
180*/
181
182int mailsession_create_folder(mailsession * session, char * mb);
183
184
185/*
186 NOTE: driver's specific should be used
187
188 mailsession_delete_folder deletes the folder that corresponds to the
189 given name
190
191 @param session the session
192 @param mb is the name of the mailbox
193
194 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
195 on error
196*/
197
198int mailsession_delete_folder(mailsession * session, char * mb);
199
200
201/*
202 mailsession_rename_folder changes the name of the folder
203
204 @param session the session
205 @param mb is the name of the mailbox whose name has to be changed
206 @param new_name is the destination name (the parent
207 of the new folder folder can be other)
208
209 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
210 on error
211*/
212
213int mailsession_rename_folder(mailsession * session,
214 char * mb, char * new_name);
215
216/*
217 mailsession_check_folder makes a checkpoint of the session
218
219 @param session the session
220
221 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
222 on error
223*/
224
225int mailsession_check_folder(mailsession * session);
226
227
228/*
229 NOTE: this function is not implemented in most drivers
230
231 mailsession_examine_folder selects a mailbox as readonly
232
233 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
234 on error
235*/
236
237int mailsession_examine_folder(mailsession * session, char * mb);
238
239
240/*
241 mailsession_select_folder selects a mailbox
242
243 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
244 on error
245*/
246
247int mailsession_select_folder(mailsession * session, char * mb);
248
249
250/*
251 mailsession_expunge_folder deletes all messages marked \Deleted
252
253 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
254 on error
255*/
256
257int mailsession_expunge_folder(mailsession * session);
258
259
260/*
261 mailsession_status_folder queries the status of the folder
262 (number of messages, number of recent messages, number of unseen messages)
263
264 @param session the session
265 @param mb mailbox to query
266 @param result_messages the number of messages is stored
267 in (* result_messages)
268 @param result_recent the number of messages is stored
269 in (* result_recent)
270 @param result_unseen the number of messages is stored
271 in (* result_unseen)
272
273 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
274 on error
275*/
276
277int mailsession_status_folder(mailsession * session, char * mb,
278 uint32_t * result_messages, uint32_t * result_recent,
279 uint32_t * result_unseen);
280
281
282/*
283 mailsession_messages_number queries the number of messages in the folder
284
285 @param session the session
286 @param mb mailbox to query
287 @param result the number of messages is stored in (* result)
288
289 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
290 on error
291*/
292
293int mailsession_messages_number(mailsession * session, char * mb,
294 uint32_t * result);
295
296/*
297 mailsession_recent_number queries the number of recent messages in the folder
298
299 @param session the session
300 @param mb mailbox to query
301 @param result the number of recent messages is stored in (* result)
302
303 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
304 on error
305*/
306
307int mailsession_recent_number(mailsession * session,
308 char * mb, uint32_t * result);
309
310/*
311 mailsession_unseen_number queries the number of unseen messages in the folder
312
313 @param session the session
314 @param mb mailbox to query
315 @param result the number of unseen messages is stored in (* result)
316
317 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
318 on error
319*/
320
321int mailsession_unseen_number(mailsession * session, char * mb,
322 uint32_t * result);
323
324/*
325 NOTE: driver's specific should be used
326
327 mailsession_list_folders returns the list of all sub-mailboxes
328 of the given mailbox
329
330 @param session the session
331 @param mb the mailbox
332 @param result list of mailboxes if stored in (* result),
333 this structure have to be freed with mail_list_free()
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error
337*/
338
339int mailsession_list_folders(mailsession * session, char * mb,
340 struct mail_list ** result);
341
342/*
343 NOTE: driver's specific should be used
344
345 mailsession_lsub_folders returns the list of subscribed
346 sub-mailboxes of the given mailbox
347
348 @param session the session
349 @param mb the mailbox
350 @param result list of mailboxes if stored in (* result),
351 this structure have to be freed with mail_list_free()
352
353 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
354 on error
355*/
356
357int mailsession_lsub_folders(mailsession * session, char * mb,
358 struct mail_list ** result);
359
360/*
361 NOTE: driver's specific should be used
362
363 mailsession_subscribe_folder subscribes to the given mailbox
364
365 @param session the session
366 @param mb the mailbox
367
368 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
369 on error
370*/
371
372int mailsession_subscribe_folder(mailsession * session, char * mb);
373
374/*
375 NOTE: driver's specific should be used
376
377 mailsession_unsubscribe_folder unsubscribes to the given mailbox
378
379 @param session the session
380 @param mb the mailbox
381
382 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
383 on error
384*/
385
386int mailsession_unsubscribe_folder(mailsession * session, char * mb);
387
388/*
389 mailsession_append_message adds a RFC 2822 message to the current
390 given mailbox
391
392 @param session the session
393 @param message is a string that contains the RFC 2822 message
394 @param size this is the size of the message
395
396 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
397 on error
398*/
399
400int mailsession_append_message(mailsession * session,
401 char * message, size_t size);
402
403int mailsession_append_message_flags(mailsession * session,
404 char * message, size_t size, struct mail_flags * flags);
405
406/*
407 NOTE: some drivers does not implement this
408
409 mailsession_copy_message copies a message whose number is given to
410 a given mailbox. The mailbox must be accessible from the same session.
411
412 @param session the session
413 @param num the message number
414 @param mb the destination mailbox
415
416 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
417 on error
418*/
419
420int mailsession_copy_message(mailsession * session,
421 uint32_t num, char * mb);
422
423/*
424 NOTE: some drivers does not implement this
425
426 mailsession_move_message copies a message whose number is given to
427 a given mailbox. The mailbox must be accessible from the same session.
428
429 @param session the session
430 @param num the message number
431 @param mb the destination mailbox
432
433 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
434 on error
435*/
436
437int mailsession_move_message(mailsession * session,
438 uint32_t num, char * mb);
439
440/*
441 mailsession_get_messages_list returns the list of message numbers
442 of the current mailbox.
443
444 @param session the session
445 @param result the list of message numbers will be stored in (* result),
446 this structure have to be freed with mailmessage_list_free()
447
448 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
449 on error
450*/
451
452int mailsession_get_messages_list(mailsession * session,
453 struct mailmessage_list ** result);
454
455/*
456 mailsession_get_envelopes_list fills the parsed fields in the
457 mailmessage structures of the mailmessage_list.
458
459 @param session the session
460 @param result this is the list of mailmessage structures
461
462 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
463 on error
464*/
465
466int mailsession_get_envelopes_list(mailsession * session,
467 struct mailmessage_list * result);
468
469/*
470 NOTE: some drivers does not implement this
471
472 mailsession_remove_message removes the given message from the mailbox.
473 The message is permanently deleted.
474
475 @param session the session
476 @param num is the message number
477
478 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
479 on error
480*/
481
482int mailsession_remove_message(mailsession * session, uint32_t num);
483
484
485/*
486 NOTE: this function is not implemented in most drivers
487
488 mailsession_search_message returns a list of message numbers that
489 corresponds to the given criteria.
490
491 @param session the session
492 @param charset is the charset to use (it can be NULL)
493 @param key is the list of criteria
494 @param result the search result is stored in (* result),
495 this structure have to be freed with mail_search_result_free()
496
497 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
498 on error
499*/
500
501#if 0
502int mailsession_search_messages(mailsession * session, char * charset,
503 struct mail_search_key * key,
504 struct mail_search_result ** result);
505#endif
506
507/*
508 mailsession_get_message returns a mailmessage structure that corresponds
509 to the given message number.
510 * WARNING * mailsession_get_message_by_uid() should be used instead.
511
512 @param session the session
513 @param num the message number
514 @param result the allocated mailmessage structure will be stored
515 in (* result), this structure have to be freed with mailmessage_free()
516
517 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
518 on error
519*/
520
521int mailsession_get_message(mailsession * session,
522 uint32_t num, mailmessage ** result);
523
524/*
525 mailsession_get_message_by_uid returns a mailmessage structure
526 that corresponds to the given message unique identifier.
527 This is currently implemented only for cached drivers.
528 * WARNING * That will deprecates the use of mailsession_get_message()
529
530 @param session the session
531 @param uid the message unique identifier
532 @param result the allocated mailmessage structure will be stored
533 in (* result), this structure have to be freed with mailmessage_free()
534
535 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
536 on error
537*/
538
539int mailsession_get_message_by_uid(mailsession * session,
540 const char * uid, mailmessage ** result);
541
542#ifdef __cplusplus
543}
544#endif
545
546#endif
diff --git a/libetpan/include/libetpan/maildriver_errors.h b/libetpan/include/libetpan/maildriver_errors.h
new file mode 100644
index 0000000..99ec25c
--- a/dev/null
+++ b/libetpan/include/libetpan/maildriver_errors.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_ERRORS_H
37
38#define MAILDRIVER_ERRORS_H
39
40enum {
41 MAIL_NO_ERROR = 0,
42 MAIL_NO_ERROR_AUTHENTICATED,
43 MAIL_NO_ERROR_NON_AUTHENTICATED,
44 MAIL_ERROR_NOT_IMPLEMENTED,
45 MAIL_ERROR_UNKNOWN,
46 MAIL_ERROR_CONNECT,
47 MAIL_ERROR_BAD_STATE,
48 MAIL_ERROR_FILE,
49 MAIL_ERROR_STREAM,
50 MAIL_ERROR_LOGIN,
51 MAIL_ERROR_CREATE, /* 10 */
52 MAIL_ERROR_DELETE,
53 MAIL_ERROR_LOGOUT,
54 MAIL_ERROR_NOOP,
55 MAIL_ERROR_RENAME,
56 MAIL_ERROR_CHECK,
57 MAIL_ERROR_EXAMINE,
58 MAIL_ERROR_SELECT,
59 MAIL_ERROR_MEMORY,
60 MAIL_ERROR_STATUS,
61 MAIL_ERROR_SUBSCRIBE, /* 20 */
62 MAIL_ERROR_UNSUBSCRIBE,
63 MAIL_ERROR_LIST,
64 MAIL_ERROR_LSUB,
65 MAIL_ERROR_APPEND,
66 MAIL_ERROR_COPY,
67 MAIL_ERROR_FETCH,
68 MAIL_ERROR_STORE,
69 MAIL_ERROR_SEARCH,
70 MAIL_ERROR_DISKSPACE,
71 MAIL_ERROR_MSG_NOT_FOUND, /* 30 */
72 MAIL_ERROR_PARSE,
73 MAIL_ERROR_INVAL,
74 MAIL_ERROR_PART_NOT_FOUND,
75 MAIL_ERROR_REMOVE,
76 MAIL_ERROR_FOLDER_NOT_FOUND,
77 MAIL_ERROR_MOVE,
78 MAIL_ERROR_STARTTLS,
79 MAIL_ERROR_CACHE_MISS,
80 MAIL_ERROR_NO_TLS,
81 MAIL_ERROR_EXPUNGE, /* 40 */
82 /* misc errors */
83 MAIL_ERROR_MISC,
84 MAIL_ERROR_PROTOCOL,
85 MAIL_ERROR_CAPABILITY,
86 MAIL_ERROR_CLOSE,
87 MAIL_ERROR_FATAL,
88 MAIL_ERROR_READONLY,
89 MAIL_ERROR_NO_APOP,
90 MAIL_ERROR_COMMAND_NOT_SUPPORTED,
91 MAIL_ERROR_NO_PERMISSION,
92 MAIL_ERROR_PROGRAM_ERROR, /* 50 */
93 MAIL_ERROR_SUBJECT_NOT_FOUND,
94 MAIL_ERROR_CHAR_ENCODING_FAILED,
95 MAIL_ERROR_SEND,
96 MAIL_ERROR_COMMAND,
97 MAIL_ERROR_SYSTEM,
98 MAIL_ERROR_UNABLE,
99 MAIL_ERROR_FOLDER,
100};
101
102#endif
diff --git a/libetpan/include/libetpan/maildriver_types.h b/libetpan/include/libetpan/maildriver_types.h
new file mode 100644
index 0000000..2225236
--- a/dev/null
+++ b/libetpan/include/libetpan/maildriver_types.h
@@ -0,0 +1,795 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_H
37
38#define MAILDRIVER_TYPES_H
39
40#include <inttypes.h>
41#include <sys/types.h>
42
43#include <libetpan/mailstream.h>
44#include <libetpan/mailimf.h>
45#include <libetpan/mailmime.h>
46#include <libetpan/carray.h>
47
48#include <libetpan/mailthread_types.h>
49#include <libetpan/maildriver_errors.h>
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55typedef struct mailsession_driver mailsession_driver;
56
57typedef struct mailsession mailsession;
58
59typedef struct mailmessage_driver mailmessage_driver;
60
61typedef struct mailmessage mailmessage;
62
63
64/*
65 mailmessage_list is a list of mailmessage
66
67 - tab is an array of mailmessage structures
68*/
69
70struct mailmessage_list {
71 carray * msg_tab; /* elements are (mailmessage *) */
72};
73
74struct mailmessage_list * mailmessage_list_new(carray * msg_tab);
75void mailmessage_list_free(struct mailmessage_list * env_list);
76
77/*
78 mail_list is a list of mailbox names
79
80 - list is a list of mailbox names
81*/
82
83struct mail_list {
84 clist * mb_list; /* elements are (char *) */
85};
86
87struct mail_list * mail_list_new(clist * mb_list);
88void mail_list_free(struct mail_list * resp);
89
90/*
91 This is a flag value.
92 Flags can be combined with OR operation
93*/
94
95enum {
96 MAIL_FLAG_NEW = 1 << 0,
97 MAIL_FLAG_SEEN = 1 << 1,
98 MAIL_FLAG_FLAGGED = 1 << 2,
99 MAIL_FLAG_DELETED = 1 << 3,
100 MAIL_FLAG_ANSWERED = 1 << 4,
101 MAIL_FLAG_FORWARDED = 1 << 5,
102 MAIL_FLAG_CANCELLED = 1 << 6,
103};
104
105/*
106 mail_flags is the value of a flag related to a message.
107
108 - flags is the standard flags value
109
110 - extension is a list of unknown flags for libEtPan!
111*/
112
113struct mail_flags {
114 uint32_t fl_flags;
115 clist * fl_extension; /* elements are (char *) */
116};
117
118struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext);
119void mail_flags_free(struct mail_flags * flags);
120
121/*
122 This function creates a flag for a new message
123*/
124
125struct mail_flags * mail_flags_new_empty(void);
126
127
128/*
129 mailimf_date_time_comp compares two dates
130
131
132*/
133
134int32_t mailimf_date_time_comp(struct mailimf_date_time * date1,
135 struct mailimf_date_time * date2);
136
137/*
138 this is type type of the search criteria
139*/
140
141enum {
142 MAIL_SEARCH_KEY_ALL, /* all messages correspond */
143 MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */
144 MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains
145 a given string */
146 MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier
147 than the specified date */
148 MAIL_SEARCH_KEY_BODY, /* message that contains the given string
149 (in header and text parts) */
150 MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the
151 given string */
152 MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */
153 MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */
154 MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the
155 given string */
156 MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not
157 the \Seen flag */
158 MAIL_SEARCH_KEY_OLD, /* messages that do not have the
159 \Recent flag set */
160 MAIL_SEARCH_KEY_ON, /* messages whose internal date is the
161 specified date */
162 MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */
163 MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */
164 MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later
165 than specified date */
166 MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the
167 given string */
168 MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the
169 given string */
170 MAIL_SEARCH_KEY_TO, /* messages whose To field contains the
171 given string */
172 MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */
173 MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */
174 MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */
175 MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */
176 MAIL_SEARCH_KEY_HEADER, /* messages whose given field
177 contains the given string */
178 MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then
179 the given size */
180 MAIL_SEARCH_KEY_NOT, /* not operation of the condition */
181 MAIL_SEARCH_KEY_OR, /* or operation between two conditions */
182 MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than
183 the given size */
184 MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the
185 conditions is AND */
186};
187
188/*
189 mail_search_key is the condition on the messages to return
190
191 - type is the type of the condition
192
193 - bcc is the text to search in the Bcc field when type is
194 MAIL_SEARCH_KEY_BCC, should be allocated with malloc()
195
196 - before is a date when type is MAIL_SEARCH_KEY_BEFORE
197
198 - body is the text to search in the message when type is
199 MAIL_SEARCH_KEY_BODY, should be allocated with malloc()
200
201 - cc is the text to search in the Cc field when type is
202 MAIL_SEARCH_KEY_CC, should be allocated with malloc()
203
204 - from is the text to search in the From field when type is
205 MAIL_SEARCH_KEY_FROM, should be allocated with malloc()
206
207 - on is a date when type is MAIL_SEARCH_KEY_ON
208
209 - since is a date when type is MAIL_SEARCH_KEY_SINCE
210
211 - subject is the text to search in the Subject field when type is
212 MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc()
213
214 - text is the text to search in the text part of the message when
215 type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc()
216
217 - to is the text to search in the To field when type is
218 MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc()
219
220 - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER,
221 should be allocated with malloc()
222
223 - header_value is the text to search in the given header when type is
224 MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc()
225
226 - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER
227
228 - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT
229
230 - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR
231
232 - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR
233
234 - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE
235
236 - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON
237
238 - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE
239
240 - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER
241
242 - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE
243*/
244
245#if 0
246struct mail_search_key {
247 int sk_type;
248 union {
249 char * sk_bcc;
250 struct mailimf_date_time * sk_before;
251 char * sk_body;
252 char * sk_cc;
253 char * sk_from;
254 struct mailimf_date_time * sk_on;
255 struct mailimf_date_time * sk_since;
256 char * sk_subject;
257 char * sk_text;
258 char * sk_to;
259 char * sk_header_name;
260 char * sk_header_value;
261 size_t sk_larger;
262 struct mail_search_key * sk_not;
263 struct mail_search_key * sk_or1;
264 struct mail_search_key * sk_or2;
265 size_t sk_smaller;
266 clist * sk_multiple; /* list of (struct mailimap_search_key *) */
267 } sk_data;
268};
269
270
271struct mail_search_key *
272mail_search_key_new(int sk_type,
273 char * sk_bcc, struct mailimf_date_time * sk_before,
274 char * sk_body, char * sk_cc, char * sk_from,
275 struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since,
276 char * sk_subject, char * sk_text, char * sk_to,
277 char * sk_header_name, char * sk_header_value, size_t sk_larger,
278 struct mail_search_key * sk_not, struct mail_search_key * sk_or1,
279 struct mail_search_key * sk_or2, size_t sk_smaller,
280 clist * sk_multiple);
281
282void mail_search_key_free(struct mail_search_key * key);
283#endif
284
285/*
286 mail_search_result is a list of message numbers that is returned
287 by the mailsession_search_messages function()
288*/
289
290#if 0
291struct mail_search_result {
292 clist * sr_list; /* list of (uint32_t *) */
293};
294
295struct mail_search_result * mail_search_result_new(clist * sr_list);
296
297void mail_search_result_free(struct mail_search_result * search_result);
298#endif
299
300
301/*
302 There is three kinds of identities :
303 - storage
304 - folders
305 - session
306
307 A storage (struct mailstorage) represents whether a server or
308 a main path,
309
310 A storage can be an IMAP server, the root path of a MH or a mbox file.
311
312 Folders (struct mailfolder) are the mailboxes we can
313 choose in the server or as sub-folder of the main path.
314
315 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
316 folder of the MH storage, for mbox, there is only one folder, the
317 mbox file content;
318
319 A mail session (struct mailsession) is whether a connection to a server
320 or a path that is open. It is the abstraction lower folders and storage.
321 It allow us to send commands.
322
323 We have a session driver for mail session for each kind of storage.
324
325 From a session, we can get a message (struct mailmessage) to read.
326 We have a message driver for each kind of storage.
327*/
328
329/*
330 maildriver is the driver structure for mail sessions
331
332 - name is the name of the driver
333
334 - initialize() is the function that will initializes a data structure
335 specific to the driver, it returns a value that will be stored
336 in the field data of the session.
337 The field data of the session is the state of the session,
338 the internal data structure used by the driver.
339 It is called when creating the mailsession structure with
340 mailsession_new().
341
342 - uninitialize() frees the structure created with initialize()
343
344 - parameters() implements functions specific to the given mail access
345
346 - connect_stream() connects a stream to the session
347
348 - connect_path() notify a main path to the session
349
350 - starttls() changes the current stream to a TLS stream
351
352 - login() notifies the user and the password to authenticate to the
353 session
354
355 - logout() exits the session and closes the stream
356
357 - noop() does no operation on the session, but it can be
358 used to poll for the status of the connection.
359
360 - build_folder_name() will return an allocated string with
361 that contains the complete path of the folder to create
362
363 - create_folder() creates the folder that corresponds to the
364 given name
365
366 - delete_folder() deletes the folder that corresponds to the
367 given name
368
369 - rename_folder() change the name of the folder
370
371 - check_folder() makes a checkpoint of the session
372
373 - examine_folder() selects a mailbox as readonly
374
375 - select_folder() selects a mailbox
376
377 - expunge_folder() deletes all messages marked \Deleted
378
379 - status_folder() queries the status of the folder
380 (number of messages, number of recent messages, number of
381 unseen messages)
382
383 - messages_number() queries the number of messages in the folder
384
385 - recent_number() queries the number of recent messages in the folder
386
387 - unseen_number() queries the number of unseen messages in the folder
388
389 - list_folders() returns the list of all sub-mailboxes
390 of the given mailbox
391
392 - lsub_folders() returns the list of subscribed
393 sub-mailboxes of the given mailbox
394
395 - subscribe_folder() subscribes to the given mailbox
396
397 - unsubscribe_folder() unsubscribes to the given mailbox
398
399 - append_message() adds a RFC 2822 message to the current
400 given mailbox
401
402 - copy_message() copies a message whose number is given to
403 a given mailbox. The mailbox must be accessible from
404 the same session.
405
406 - move_message() copies a message whose number is given to
407 a given mailbox. The mailbox must be accessible from the
408 same session.
409
410 - get_messages_list() returns the list of message numbers
411 of the current mailbox.
412
413 - get_envelopes_list() fills the parsed fields in the
414 mailmessage structures of the mailmessage_list.
415
416 - remove_message() removes the given message from the mailbox.
417 The message is permanently deleted.
418
419 - search_message() returns a list of message numbers that
420 corresponds to the given criteria.
421
422 - get_message returns a mailmessage structure that corresponds
423 to the given message number.
424
425 - get_message_by_uid returns a mailmessage structure that corresponds
426 to the given message unique identifier.
427
428 * mandatory functions are the following :
429
430 - connect_stream() of connect_path()
431 - logout()
432 - get_messages_list()
433 - get_envelopes_list()
434
435 * we advise you to implement these functions :
436
437 - select_folder() (in case a session can access several folders)
438 - noop() (to check if the server is responding)
439 - check_folder() (to make a checkpoint of the session)
440 - status_folder(), messages_number(), recent_number(), unseen_number()
441 (to get stat of the folder)
442 - append_message() (but can't be done in the case of POP3 at least)
443 - login() in a case of an authenticated driver.
444 - starttls() in a case of a stream driver, if the procotol supports
445 STARTTLS.
446 - get_message_by_uid() so that the application can remember the message
447 by UID and build its own list of messages.
448
449 * drivers' specific :
450
451 Everything that is specific to the driver will be implemented in this
452 function :
453
454 - parameters()
455*/
456
457struct mailsession_driver {
458 char * sess_name;
459
460 int (* sess_initialize)(mailsession * session);
461 void (* sess_uninitialize)(mailsession * session);
462
463 int (* sess_parameters)(mailsession * session,
464 int id, void * value);
465
466 int (* sess_connect_stream)(mailsession * session, mailstream * s);
467 int (* sess_connect_path)(mailsession * session, char * path);
468
469 int (* sess_starttls)(mailsession * session);
470
471 int (* sess_login)(mailsession * session, char * userid, char * password);
472 int (* sess_logout)(mailsession * session);
473 int (* sess_noop)(mailsession * session);
474
475 /* folders operations */
476
477 int (* sess_build_folder_name)(mailsession * session, char * mb,
478 char * name, char ** result);
479
480 int (* sess_create_folder)(mailsession * session, char * mb);
481 int (* sess_delete_folder)(mailsession * session, char * mb);
482 int (* sess_rename_folder)(mailsession * session, char * mb,
483 char * new_name);
484 int (* sess_check_folder)(mailsession * session);
485 int (* sess_examine_folder)(mailsession * session, char * mb);
486 int (* sess_select_folder)(mailsession * session, char * mb);
487 int (* sess_expunge_folder)(mailsession * session);
488 int (* sess_status_folder)(mailsession * session, char * mb,
489 uint32_t * result_num, uint32_t * result_recent,
490 uint32_t * result_unseen);
491 int (* sess_messages_number)(mailsession * session, char * mb,
492 uint32_t * result);
493 int (* sess_recent_number)(mailsession * session, char * mb,
494 uint32_t * result);
495 int (* sess_unseen_number)(mailsession * session, char * mb,
496 uint32_t * result);
497
498 int (* sess_list_folders)(mailsession * session, char * mb,
499 struct mail_list ** result);
500 int (* sess_lsub_folders)(mailsession * session, char * mb,
501 struct mail_list ** result);
502
503 int (* sess_subscribe_folder)(mailsession * session, char * mb);
504 int (* sess_unsubscribe_folder)(mailsession * session, char * mb);
505
506 /* messages operations */
507
508 int (* sess_append_message)(mailsession * session,
509 char * message, size_t size);
510 int (* sess_append_message_flags)(mailsession * session,
511 char * message, size_t size, struct mail_flags * flags);
512 int (* sess_copy_message)(mailsession * session,
513 uint32_t num, char * mb);
514 int (* sess_move_message)(mailsession * session,
515 uint32_t num, char * mb);
516
517 int (* sess_get_message)(mailsession * session,
518 uint32_t num, mailmessage ** result);
519
520 int (* sess_get_message_by_uid)(mailsession * session,
521 const char * uid, mailmessage ** result);
522
523 int (* sess_get_messages_list)(mailsession * session,
524 struct mailmessage_list ** result);
525 int (* sess_get_envelopes_list)(mailsession * session,
526 struct mailmessage_list * env_list);
527 int (* sess_remove_message)(mailsession * session, uint32_t num);
528#if 0
529 int (* sess_search_messages)(mailsession * session, char * charset,
530 struct mail_search_key * key,
531 struct mail_search_result ** result);
532#endif
533};
534
535
536/*
537 session is the data structure for a mail session.
538
539 - data is the internal data structure used by the driver
540 It is called when initializing the mailsession structure.
541
542 - driver is the driver used for the session
543*/
544
545struct mailsession {
546 void * sess_data;
547 mailsession_driver * sess_driver;
548};
549
550
551
552
553/*
554 mailmessage_driver is the driver structure to get information from messages.
555
556 - name is the name of the driver
557
558 - initialize() is the function that will initializes a data structure
559 specific to the driver, it returns a value that will be stored
560 in the field data of the mailsession.
561 The field data of the session is the state of the session,
562 the internal data structure used by the driver.
563 It is called when initializing the mailmessage structure with
564 mailmessage_init().
565
566 - uninitialize() frees the structure created with initialize().
567 It will be called by mailmessage_free().
568
569 - flush() will free from memory all temporary structures of the message
570 (for example, the MIME structure of the message).
571
572 - fetch_result_free() will free all strings resulted by fetch() or
573 any fetch_xxx() functions that returns a string.
574
575 - fetch() returns the content of the message (headers and text).
576
577 - fetch_header() returns the content of the headers.
578
579 - fetch_body() returns the message text (message content without headers)
580
581 - fetch_size() returns the size of the message content.
582
583 - get_bodystructure() returns the MIME structure of the message.
584
585 - fetch_section() returns the content of a given MIME part
586
587 - fetch_section_header() returns the header of the message
588 contained by the given MIME part.
589
590 - fetch_section_mime() returns the MIME headers of the
591 given MIME part.
592
593 - fetch_section_body() returns the text (if this is a message, this is the
594 message content without headers) of the given MIME part.
595
596 - fetch_envelope() returns a mailimf_fields structure, with a list of
597 fields chosen by the driver.
598
599 - get_flags() returns a the flags related to the message.
600 When you want to get flags of a message, you have to make sure to
601 call get_flags() at least once before using directly message->flags.
602*/
603
604#define LIBETPAN_MAIL_MESSAGE_CHECK
605
606struct mailmessage_driver {
607 char * msg_name;
608
609 int (* msg_initialize)(mailmessage * msg_info);
610
611 void (* msg_uninitialize)(mailmessage * msg_info);
612
613 void (* msg_flush)(mailmessage * msg_info);
614
615 void (* msg_check)(mailmessage * msg_info);
616
617 void (* msg_fetch_result_free)(mailmessage * msg_info,
618 char * msg);
619
620 int (* msg_fetch)(mailmessage * msg_info,
621 char ** result,
622 size_t * result_len);
623
624 int (* msg_fetch_header)(mailmessage * msg_info,
625 char ** result,
626 size_t * result_len);
627
628 int (* msg_fetch_body)(mailmessage * msg_info,
629 char ** result, size_t * result_len);
630
631 int (* msg_fetch_size)(mailmessage * msg_info,
632 size_t * result);
633
634 int (* msg_get_bodystructure)(mailmessage * msg_info,
635 struct mailmime ** result);
636
637 int (* msg_fetch_section)(mailmessage * msg_info,
638 struct mailmime * mime,
639 char ** result, size_t * result_len);
640
641 int (* msg_fetch_section_header)(mailmessage * msg_info,
642 struct mailmime * mime,
643 char ** result,
644 size_t * result_len);
645
646 int (* msg_fetch_section_mime)(mailmessage * msg_info,
647 struct mailmime * mime,
648 char ** result,
649 size_t * result_len);
650
651 int (* msg_fetch_section_body)(mailmessage * msg_info,
652 struct mailmime * mime,
653 char ** result,
654 size_t * result_len);
655
656 int (* msg_fetch_envelope)(mailmessage * msg_info,
657 struct mailimf_fields ** result);
658
659 int (* msg_get_flags)(mailmessage * msg_info,
660 struct mail_flags ** result);
661};
662
663
664/*
665 mailmessage is a data structure to get information from messages
666
667 - session is the session linked to the given message, it can be NULL
668
669 - driver is the message driver
670
671 - index is the message number
672
673 - uid, when it is not NULL, it means that the folder
674 the folder has persistant message numbers, the string is
675 the unique message number in the folder.
676 uid should be implemented if possible.
677 for drivers where we cannot generate real uid,
678 a suggestion is "AAAA-IIII" where AAAA is some
679 random session number and IIII the content of index field.
680
681 - size, when it is not 0, is the size of the message content.
682
683 - fields, when it is not NULL, are the header fields of the message.
684
685 - flags, when it is not NULL, are the flags related to the message.
686
687 - single_fields, when resolved != 0, is filled with the data of fields.
688
689 - mime, when it is not NULL
690
691 - cached is != 0 when the header fields were read from the cache.
692
693 - data is data specific to the driver, this is internal data structure,
694 some state of the message.
695*/
696
697struct mailmessage {
698 mailsession * msg_session;
699 mailmessage_driver * msg_driver;
700 uint32_t msg_index;
701 char * msg_uid;
702
703 size_t msg_size;
704 struct mailimf_fields * msg_fields;
705 struct mail_flags * msg_flags;
706
707 int msg_resolved;
708 struct mailimf_single_fields msg_single_fields;
709 struct mailmime * msg_mime;
710
711 /* internal data */
712
713 int msg_cached;
714 void * msg_data;
715
716 /*
717 msg_folder field :
718 used to reference the mailfolder, this is a workaround due
719 to the problem with initial conception, where folder notion
720 did not exist.
721 */
722 void * msg_folder;
723 /* user data */
724 void * msg_user_data;
725};
726
727
728/*
729 mailmessage_tree is a node in the messages tree (thread)
730
731 - parent is the parent of the message, it is NULL if the message
732 is the root of the message tree.
733
734 - date is the date of the message in number of second elapsed
735 since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
736
737 - msg is the message structure that is stored referenced by the node.
738 is msg is NULL, this is a dummy node.
739
740 - children is an array that contains all the children of the node.
741 children are mailmessage_tree structures.
742
743 - is_reply is != 0 when the message is a reply or a forward
744
745 - base_subject is the extracted subject of the message.
746
747 - index is the message number.
748*/
749
750struct mailmessage_tree {
751 struct mailmessage_tree * node_parent;
752 char * node_msgid;
753 time_t node_date;
754 mailmessage * node_msg;
755 carray * node_children; /* array of (struct mailmessage_tree *) */
756
757 /* private, used for threading */
758 int node_is_reply;
759 char * node_base_subject;
760};
761
762
763struct mailmessage_tree *
764mailmessage_tree_new(char * node_msgid, time_t node_date,
765 mailmessage * node_msg);
766
767void mailmessage_tree_free(struct mailmessage_tree * tree);
768
769/*
770 mailmessage_tree_free_recursive
771
772 if you want to release memory of the given tree and all the sub-trees,
773 you can use this function.
774*/
775
776void mailmessage_tree_free_recursive(struct mailmessage_tree * tree);
777
778
779struct generic_message_t {
780 int (* msg_prefetch)(mailmessage * msg_info);
781 void (* msg_prefetch_free)(struct generic_message_t * msg);
782 int msg_fetched;
783 char * msg_message;
784 size_t msg_length;
785 void * msg_data;
786};
787
788
789const char * maildriver_strerror(int err);
790
791#ifdef __cplusplus
792}
793#endif
794
795#endif
diff --git a/libetpan/include/libetpan/maildriver_types_helper.h b/libetpan/include/libetpan/maildriver_types_helper.h
new file mode 100644
index 0000000..50ccc70
--- a/dev/null
+++ b/libetpan/include/libetpan/maildriver_types_helper.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_HELPER_H
37
38#define MAILDRIVER_TYPES_HELPER_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_flags_add_extension adds the given flag if it does not exists in
48 the flags.
49
50 @param flags this is the flag to change
51
52 @param ext_flag this is the name of an extension flag
53 the given flag name is duplicated and is no more needed after
54 the function call.
55
56 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
57 on error
58*/
59
60int mail_flags_add_extension(struct mail_flags * flags,
61 char * ext_flag);
62
63/*
64 mail_flags_remove_extension removes the given flag if it does not exists in
65 the flags.
66
67 @param flags this is the flag to change
68
69 @param ext_flag this is the name of an extension flag
70 the given flag name is no more needed after the function call.
71
72 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
73 on error
74*/
75
76int mail_flags_remove_extension(struct mail_flags * flags,
77 char * ext_flag);
78
79/*
80 mail_flags_has_extension returns 1 if the flags is in the given flags,
81 0 is returned otherwise.
82
83 @param flags this is the flag to change
84
85 @param ext_flag this is the name of an extension flag
86 the given flag name is no more needed after the function call.
87
88 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
89 on error
90*/
91
92int mail_flags_has_extension(struct mail_flags * flags,
93 char * ext_flag);
94
95#ifdef __cplusplus
96}
97#endif
98
99#endif
diff --git a/libetpan/include/libetpan/mailengine.h b/libetpan/include/libetpan/mailengine.h
new file mode 100644
index 0000000..acb6a16
--- a/dev/null
+++ b/libetpan/include/libetpan/mailengine.h
@@ -0,0 +1,190 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILENGINE_H
37
38#define MAILENGINE_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailfolder.h>
42#include <libetpan/mailprivacy_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/*
49 to run things in thread, you must protect the storage again concurrency.
50*/
51
52
53/*
54 storage data
55*/
56
57struct mailengine *
58libetpan_engine_new(struct mailprivacy * privacy);
59
60void libetpan_engine_free(struct mailengine * engine);
61
62
63struct mailprivacy *
64libetpan_engine_get_privacy(struct mailengine * engine);
65
66
67/*
68 message ref and unref
69*/
70
71/*
72 these function can only take messages returned by get_msg_list()
73 as arguments.
74
75 these functions cannot fail.
76*/
77
78int libetpan_message_ref(struct mailengine * engine,
79 mailmessage * msg);
80
81int libetpan_message_unref(struct mailengine * engine,
82 mailmessage * msg);
83
84
85/*
86 when you want to access the MIME structure of the message
87 with msg->mime, you have to call libetpan_message_mime_ref()
88 and libetpan_message_mime_unref() when you have finished.
89
90 if libetpan_mime_ref() returns a value <= 0, it means this failed.
91 the value is -MAIL_ERROR_XXX
92*/
93
94int libetpan_message_mime_ref(struct mailengine * engine,
95 mailmessage * msg);
96
97int libetpan_message_mime_unref(struct mailengine * engine,
98 mailmessage * msg);
99
100/*
101 message list
102*/
103
104/*
105 libetpan_folder_get_msg_list()
106
107 This function returns two list.
108 - List of lost message (the messages that were previously returned
109 but that does no more exist) (p_lost_msg_list)
110 - List of valid messages (p_new_msg_list).
111
112 These two list can only be freed by libetpan_folder_free_msg_list()
113*/
114
115int libetpan_folder_get_msg_list(struct mailengine * engine,
116 struct mailfolder * folder,
117 struct mailmessage_list ** p_new_msg_list,
118 struct mailmessage_list ** p_lost_msg_list);
119
120int libetpan_folder_fetch_env_list(struct mailengine * engine,
121 struct mailfolder * folder,
122 struct mailmessage_list * msg_list);
123
124void libetpan_folder_free_msg_list(struct mailengine * engine,
125 struct mailfolder * folder,
126 struct mailmessage_list * env_list);
127
128
129/*
130 connect and disconnect storage
131*/
132
133int libetpan_storage_add(struct mailengine * engine,
134 struct mailstorage * storage);
135
136void libetpan_storage_remove(struct mailengine * engine,
137 struct mailstorage * storage);
138
139int libetpan_storage_connect(struct mailengine * engine,
140 struct mailstorage * storage);
141
142void libetpan_storage_disconnect(struct mailengine * engine,
143 struct mailstorage * storage);
144
145int libetpan_storage_used(struct mailengine * engine,
146 struct mailstorage * storage);
147
148
149/*
150 libetpan_folder_connect()
151 libetpan_folder_disconnect()
152
153 You can disconnect the folder only when you have freed all the message
154 you were given.
155*/
156
157int libetpan_folder_connect(struct mailengine * engine,
158 struct mailfolder * folder);
159
160void libetpan_folder_disconnect(struct mailengine * engine,
161 struct mailfolder * folder);
162
163
164struct mailfolder *
165libetpan_message_get_folder(struct mailengine * engine,
166 mailmessage * msg);
167
168struct mailstorage *
169libetpan_message_get_storage(struct mailengine * engine,
170 mailmessage * msg);
171
172
173/*
174 register a message
175*/
176
177int libetpan_message_register(struct mailengine * engine,
178 struct mailfolder * folder,
179 mailmessage * msg);
180
181
182void libetpan_engine_debug(struct mailengine * engine, FILE * f);
183
184extern void * engine_app;
185
186#ifdef __cplusplus
187}
188#endif
189
190#endif
diff --git a/libetpan/include/libetpan/mailfolder.h b/libetpan/include/libetpan/mailfolder.h
new file mode 100644
index 0000000..55ea3be
--- a/dev/null
+++ b/libetpan/include/libetpan/mailfolder.h
@@ -0,0 +1,70 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILFOLDER_H
37
38#define MAILFOLDER_H
39
40#include "mailstorage_types.h"
41
42int mailfolder_noop(struct mailfolder * folder);
43
44int mailfolder_check(struct mailfolder * folder);
45
46int mailfolder_expunge(struct mailfolder * folder);
47
48int mailfolder_status(struct mailfolder * folder,
49 uint32_t * result_messages, uint32_t * result_recent,
50 uint32_t * result_unseen);
51
52int mailfolder_append_message(struct mailfolder * folder,
53 char * message, size_t size);
54
55int mailfolder_append_message_flags(struct mailfolder * folder,
56 char * message, size_t size, struct mail_flags * flags);
57
58int mailfolder_get_messages_list(struct mailfolder * folder,
59 struct mailmessage_list ** result);
60
61int mailfolder_get_envelopes_list(struct mailfolder * folder,
62 struct mailmessage_list * result);
63
64int mailfolder_get_message(struct mailfolder * folder,
65 uint32_t num, mailmessage ** result);
66
67int mailfolder_get_message_by_uid(struct mailfolder * folder,
68 const char * uid, mailmessage ** result);
69
70#endif
diff --git a/libetpan/include/libetpan/mailimap.h b/libetpan/include/libetpan/mailimap.h
new file mode 100644
index 0000000..e31e2d2
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap.h
@@ -0,0 +1,598 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_H
37
38#define MAILIMAP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45#include <libetpan/mailimap_types_helper.h>
46#include <libetpan/mailimap_helper.h>
47
48#include <libetpan/mailimap_socket.h>
49#include <libetpan/mailimap_ssl.h>
50
51/*
52 mailimap_connect()
53
54 This function will connect the IMAP session with the given stream.
55
56 @param session the IMAP session
57 @param s stream to use
58
59 @return the return code is one of MAILIMAP_ERROR_XXX or
60 MAILIMAP_NO_ERROR codes
61
62 note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or
63 MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned
64
65 MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to
66 use mailimap_login() to authenticate, else
67 MAILIMAP_NO_ERROR_AUTHENTICATED is returned.
68*/
69
70int mailimap_connect(mailimap * session, mailstream * s);
71
72/*
73 mailimap_append()
74
75 This function will append a given message to the given mailbox
76 by sending an APPEND command.
77
78 @param session the IMAP session
79 @param mailbox name of the mailbox
80 @param flag_list flags of the message
81 @param date_time timestamp of the message
82 @param literal content of the message
83 @param literal_size size of the message
84
85 @return the return code is one of MAILIMAP_ERROR_XXX or
86 MAILIMAP_NO_ERROR codes
87*/
88
89int mailimap_append(mailimap * session, const char * mailbox,
90 struct mailimap_flag_list * flag_list,
91 struct mailimap_date_time * date_time,
92 const char * literal, size_t literal_size);
93
94/*
95 mailimap_noop()
96
97 This function will poll for an event on the server by
98 sending a NOOP command to the IMAP server
99
100 @param session IMAP session
101
102 @return the return code is one of MAILIMAP_ERROR_XXX or
103 MAILIMAP_NO_ERROR_XXX codes
104*/
105
106int mailimap_noop(mailimap * session);
107
108/*
109 mailimap_logout()
110
111 This function will logout from an IMAP server by sending
112 a LOGOUT command.
113
114 @param session IMAP session
115
116 @return the return code is one of MAILIMAP_ERROR_XXX or
117 MAILIMAP_NO_ERROR codes
118*/
119
120int mailimap_logout(mailimap * session);
121
122/*
123 mailimap_capability()
124
125 This function will query an IMAP server for his capabilities
126 by sending a CAPABILITY command.
127
128 @param session IMAP session
129 @param result The result of this command is a list of
130 capabilities and it is stored into (* result).
131
132 @return the return code is one of MAILIMAP_ERROR_XXX or
133 MAILIMAP_NO_ERROR codes
134 */
135
136int mailimap_capability(mailimap * session,
137 struct mailimap_capability_data ** result);
138
139/*
140 mailimap_check()
141
142 This function will request for a checkpoint of the mailbox by
143 sending a CHECK command.
144
145 @param session IMAP session
146
147 @return the return code is one of MAILIMAP_ERROR_XXX or
148 MAILIMAP_NO_ERROR codes
149 */
150
151int mailimap_check(mailimap * session);
152
153/*
154 mailimap_close()
155
156 This function will close the selected mailbox by sending
157 a CLOSE command.
158
159 @param session IMAP session
160
161 @return the return code is one of MAILIMAP_ERROR_XXX or
162 MAILIMAP_NO_ERROR codes
163 */
164
165int mailimap_close(mailimap * session);
166
167/*
168 mailimap_expunge()
169
170 This function will permanently remove from the selected mailbox
171 message that have the \Deleted flag set.
172
173 @param session IMAP session
174
175 @return the return code is one of MAILIMAP_ERROR_XXX or
176 MAILIMAP_NO_ERROR codes
177*/
178
179int mailimap_expunge(mailimap * session);
180
181/*
182 mailimap_copy()
183
184 This function will copy the given messages from the selected mailbox
185 to the given mailbox.
186
187 @param session IMAP session
188 @param set This is a set of message numbers.
189 @param mb This is the destination mailbox.
190
191 @return the return code is one of MAILIMAP_ERROR_XXX or
192 MAILIMAP_NO_ERROR codes
193 */
194
195int mailimap_copy(mailimap * session, struct mailimap_set * set,
196 const char * mb);
197
198/*
199 mailimap_uid_copy()
200
201 This function will copy the given messages from the selected mailbox
202 to the given mailbox.
203
204 @param session IMAP session
205 @param set This is a set of message unique identifiers.
206 @param mb This is the destination mailbox.
207
208 @return the return code is one of MAILIMAP_ERROR_XXX or
209 MAILIMAP_NO_ERROR codes
210 */
211
212int mailimap_uid_copy(mailimap * session,
213 struct mailimap_set * set, const char * mb);
214
215/*
216 mailimap_create()
217
218 This function will create a mailbox.
219
220 @param session IMAP session
221 @param mb This is the name of the mailbox to create.
222
223 @return the return code is one of MAILIMAP_ERROR_XXX or
224 MAILIMAP_NO_ERROR codes
225*/
226
227int mailimap_create(mailimap * session, const char * mb);
228
229/*
230 mailimap_delete()
231
232 This function will delete a mailox.
233
234 @param session IMAP session
235 @param mb This is the name of the mailbox to delete.
236
237 @return the return code is one of MAILIMAP_ERROR_XXX or
238 MAILIMAP_NO_ERROR codes
239*/
240
241int mailimap_delete(mailimap * session, const char * mb);
242
243/*
244 mailimap_examine()
245
246 This function will select the mailbox for read-only operations.
247
248 @param session IMAP session
249 @param mb This is the name of the mailbox to select.
250
251 @return the return code is one of MAILIMAP_ERROR_XXX or
252 MAILIMAP_NO_ERROR codes
253*/
254
255int mailimap_examine(mailimap * session, const char * mb);
256
257/*
258 mailimap_fetch()
259
260 This function will retrieve data associated with the given message
261 numbers.
262
263 @param session IMAP session
264 @param set set of message numbers
265 @param fetch_type type of information to be retrieved
266 @param result The result of this command is a clist
267 and it is stored into (* result). Each element of the clist is a
268 (struct mailimap_msg_att *).
269
270 @return the return code is one of MAILIMAP_ERROR_XXX or
271 MAILIMAP_NO_ERROR codes
272*/
273
274int
275mailimap_fetch(mailimap * session, struct mailimap_set * set,
276 struct mailimap_fetch_type * fetch_type, clist ** result);
277
278/*
279 mailimap_fetch()
280
281 This function will retrieve data associated with the given message
282 numbers.
283
284 @param session IMAP session
285 @param set set of message unique identifiers
286 @param fetch_type type of information to be retrieved
287 @param result The result of this command is a clist
288 and it is stored into (* result). Each element of the clist is a
289 (struct mailimap_msg_att *).
290
291 @return the return code is one of MAILIMAP_ERROR_XXX or
292 MAILIMAP_NO_ERROR codes
293*/
294
295int
296mailimap_uid_fetch(mailimap * session,
297 struct mailimap_set * set,
298 struct mailimap_fetch_type * fetch_type, clist ** result);
299
300/*
301 mailimap_fetch_list_free()
302
303 This function will free the result of a fetch command.
304
305 @param fetch_list This is the clist containing
306 (struct mailimap_msg_att *) elements to free.
307*/
308
309void mailimap_fetch_list_free(clist * fetch_list);
310
311/*
312 mailimap_list()
313
314 This function will return the list of the mailbox
315 available on the server.
316
317 @param session IMAP session
318 @param mb This is the reference name that informs
319 of the level of hierarchy
320 @param list_mb mailbox name with possible wildcard
321 @param result This will store a clist of (struct mailimap_mailbox_list *)
322 in (* result)
323
324 @return the return code is one of MAILIMAP_ERROR_XXX or
325 MAILIMAP_NO_ERROR codes
326*/
327
328int mailimap_list(mailimap * session, const char * mb,
329 const char * list_mb, clist ** result);
330
331/*
332 mailimap_login()
333
334 This function will authenticate the client.
335
336 @param session IMAP session
337 @param userid login of the user
338 @param password password of the user
339
340 @return the return code is one of MAILIMAP_ERROR_XXX or
341 MAILIMAP_NO_ERROR codes
342*/
343
344int mailimap_login(mailimap * session,
345 const char * userid, const char * password);
346
347/*
348 mailimap_lsub()
349
350 This function will return the list of the mailbox
351 that the client has subscribed to.
352
353 @param session IMAP session
354 @param mb This is the reference name that informs
355 of the level of hierarchy
356 @param list_mb mailbox name with possible wildcard
357 @param result This will store a list of (struct mailimap_mailbox_list *)
358 in (* result)
359
360 @return the return code is one of MAILIMAP_ERROR_XXX or
361 MAILIMAP_NO_ERROR codes
362*/
363
364int mailimap_lsub(mailimap * session, const char * mb,
365 const char * list_mb, clist ** result);
366
367/*
368 mailimap_list_result_free()
369
370 This function will free the clist of (struct mailimap_mailbox_list *)
371
372 @param list This is the clist to free.
373*/
374
375void mailimap_list_result_free(clist * list);
376
377/*
378 mailimap_rename()
379
380 This function will change the name of a mailbox.
381
382 @param session IMAP session
383 @param mb current name
384 @param new_name new name
385
386 @return the return code is one of MAILIMAP_ERROR_XXX or
387 MAILIMAP_NO_ERROR codes
388*/
389
390int mailimap_rename(mailimap * session,
391 const char * mb, const char * new_name);
392
393/*
394 mailimap_search()
395
396 All mails that match the given criteria will be returned
397 their numbers in the result list.
398
399 @param session IMAP session
400 @param charset This indicates the charset of the strings that appears
401 in the searching criteria
402 @param key This is the searching criteria
403 @param result The result is a clist of (uint32_t *) and will be
404 stored in (* result).
405
406 @return the return code is one of MAILIMAP_ERROR_XXX or
407 MAILIMAP_NO_ERROR codes
408*/
409
410int
411mailimap_search(mailimap * session, const char * charset,
412 struct mailimap_search_key * key, clist ** result);
413
414/*
415 mailimap_uid_search()
416
417
418 All mails that match the given criteria will be returned
419 their unique identifiers in the result list.
420
421 @param session IMAP session
422 @param charset This indicates the charset of the strings that appears
423 in the searching criteria
424 @param key This is the searching criteria
425 @param result The result is a clist of (uint32_t *) and will be
426 stored in (* result).
427
428 @return the return code is one of MAILIMAP_ERROR_XXX or
429 MAILIMAP_NO_ERROR codes
430*/
431
432int
433mailimap_uid_search(mailimap * session, const char * charset,
434 struct mailimap_search_key * key, clist ** result);
435
436/*
437 mailimap_search_result_free()
438
439 This function will free the result of the a search.
440
441 @param search_result This is a clist of (uint32_t *) returned
442 by mailimap_uid_search() or mailimap_search()
443*/
444
445void mailimap_search_result_free(clist * search_result);
446
447/*
448 mailimap_select()
449
450 This function will select a given mailbox so that messages in the
451 mailbox can be accessed.
452
453 @param session IMAP session
454 @param mb This is the name of the mailbox to select.
455
456 @return the return code is one of MAILIMAP_ERROR_XXX or
457 MAILIMAP_NO_ERROR codes
458*/
459
460int
461mailimap_select(mailimap * session, const char * mb);
462
463/*
464 mailimap_status()
465
466 This function will return informations about a given mailbox.
467
468 @param session IMAP session
469 @param mb This is the name of the mailbox
470 @param status_att_list This is the list of mailbox information to return
471 @param result List of returned values
472
473 @return the return code is one of MAILIMAP_ERROR_XXX or
474 MAILIMAP_NO_ERROR codes
475*/
476
477int
478mailimap_status(mailimap * session, const char * mb,
479 struct mailimap_status_att_list * status_att_list,
480 struct mailimap_mailbox_data_status ** result);
481
482/*
483 mailimap_uid_store()
484
485 This function will alter the data associated with some messages
486 (flags of the messages).
487
488 @param session IMAP session
489 @param set This is a list of message numbers.
490 @param store_att_flags This is the data to associate with the
491 given messages
492
493 @return the return code is one of MAILIMAP_ERROR_XXX or
494 MAILIMAP_NO_ERROR codes
495*/
496
497int
498mailimap_store(mailimap * session,
499 struct mailimap_set * set,
500 struct mailimap_store_att_flags * store_att_flags);
501
502/*
503 mailimap_uid_store()
504
505 This function will alter the data associated with some messages
506 (flags of the messages).
507
508 @param session IMAP session
509 @param set This is a list of message unique identifiers.
510 @param store_att_flags This is the data to associate with the
511 given messages
512
513 @return the return code is one of MAILIMAP_ERROR_XXX or
514 MAILIMAP_NO_ERROR codes
515*/
516
517int
518mailimap_uid_store(mailimap * session,
519 struct mailimap_set * set,
520 struct mailimap_store_att_flags * store_att_flags);
521
522/*
523 mailimap_subscribe()
524
525 This function adds the specified mailbox name to the
526 server's set of "active" or "subscribed" mailboxes.
527
528 @param session IMAP session
529 @param mb This is the name of the mailbox
530
531 @return the return code is one of MAILIMAP_ERROR_XXX or
532 MAILIMAP_NO_ERROR codes
533*/
534
535int mailimap_subscribe(mailimap * session, const char * mb);
536
537/*
538 mailimap_unsubscribe()
539
540 This function removes the specified mailbox name to the
541 server's set of "active" or "subscribed" mailboxes.
542
543 @param session IMAP session
544 @param mb This is the name of the mailbox
545
546 @return the return code is one of MAILIMAP_ERROR_XXX or
547 MAILIMAP_NO_ERROR codes
548*/
549
550int mailimap_unsubscribe(mailimap * session, const char * mb);
551
552/*
553 mailimap_starttls()
554
555 This function starts change the mode of the connection to
556 switch to SSL connection.
557
558 @param session IMAP session
559
560 @return the return code is one of MAILIMAP_ERROR_XXX or
561 MAILIMAP_NO_ERROR_XXX codes
562 */
563
564int mailimap_starttls(mailimap * session);
565
566/*
567 mailimap_new()
568
569 This function returns a new IMAP session.
570
571 @param progr_rate When downloading messages, a function will be called
572 each time the amount of bytes downloaded reaches a multiple of this
573 value, this can be 0.
574 @param progr_fun This is the function to call to notify the progress,
575 this can be NULL.
576
577 @return an IMAP session is returned.
578 */
579
580mailimap * mailimap_new(size_t imap_progr_rate,
581 progress_function * imap_progr_fun);
582
583/*
584 mailimap_free()
585
586 This function will free the data structures associated with
587 the IMAP session.
588
589 @param session IMAP session
590 */
591
592void mailimap_free(mailimap * session);
593
594#ifdef __cplusplus
595}
596#endif
597
598#endif
diff --git a/libetpan/include/libetpan/mailimap_helper.h b/libetpan/include/libetpan/mailimap_helper.h
new file mode 100644
index 0000000..b548271
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap_helper.h
@@ -0,0 +1,66 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_HELPER_H
37
38#define MAILIMAP_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45
46int mailimap_fetch_rfc822(mailimap * session,
47 uint32_t msgid, char ** result);
48
49int mailimap_fetch_rfc822_header(mailimap * session,
50 uint32_t msgid, char ** result);
51
52int mailimap_fetch_envelope(mailimap * session,
53 uint32_t first, uint32_t last,
54 clist ** result);
55
56int mailimap_append_simple(mailimap * session, char * mailbox,
57 char * content, uint32_t size);
58
59int mailimap_login_simple(mailimap * session,
60 char * userid, char * password);
61
62#ifdef __cplusplus
63}
64#endif
65
66#endif
diff --git a/libetpan/include/libetpan/mailimap_socket.h b/libetpan/include/libetpan/mailimap_socket.h
new file mode 100644
index 0000000..ed8f369
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap_socket.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_SOCKET_H
37
38#define MAILIMAP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailimap_types.h>
47
48int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/include/libetpan/mailimap_ssl.h b/libetpan/include/libetpan/mailimap_ssl.h
new file mode 100644
index 0000000..4d5146c
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap_ssl.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_SSL_H
37
38#define MAILIMAP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailimap_types.h>
47
48int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/include/libetpan/mailimap_types.h b/libetpan/include/libetpan/mailimap_types.h
new file mode 100644
index 0000000..532d2c0
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap_types.h
@@ -0,0 +1,3274 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 IMAP4rev1 grammar
38
39 address = "(" addr-name SP addr-adl SP addr-mailbox SP
40 addr-host ")"
41
42 addr-adl = nstring
43 ; Holds route from [RFC-822] route-addr if
44 ; non-NIL
45
46 addr-host = nstring
47 ; NIL indicates [RFC-822] group syntax.
48 ; Otherwise, holds [RFC-822] domain name
49
50 addr-mailbox = nstring
51 ; NIL indicates end of [RFC-822] group; if
52 ; non-NIL and addr-host is NIL, holds
53 ; [RFC-822] group name.
54 ; Otherwise, holds [RFC-822] local-part
55 ; after removing [RFC-822] quoting
56
57
58
59 addr-name = nstring
60 ; If non-NIL, holds phrase from [RFC-822]
61 ; mailbox after removing [RFC-822] quoting
62
63 append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
64 literal
65
66 astring = 1*ASTRING-CHAR / string
67
68 ASTRING-CHAR = ATOM-CHAR / resp-specials
69
70 atom = 1*ATOM-CHAR
71
72 ATOM-CHAR = <any CHAR except atom-specials>
73
74 atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
75 quoted-specials / resp-specials
76
77 authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
78
79 auth-type = atom
80 ; Defined by [SASL]
81
82 base64 = *(4base64-char) [base64-terminal]
83
84 base64-char = ALPHA / DIGIT / "+" / "/"
85 ; Case-sensitive
86
87 base64-terminal = (2base64-char "==") / (3base64-char "=")
88
89 body = "(" (body-type-1part / body-type-mpart) ")"
90
91 body-extension = nstring / number /
92 "(" body-extension *(SP body-extension) ")"
93 ; Future expansion. Client implementations
94 ; MUST accept body-extension fields. Server
95 ; implementations MUST NOT generate
96 ; body-extension fields except as defined by
97 ; future standard or standards-track
98 ; revisions of this specification.
99
100 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
101 *(SP body-extension)]]
102 ; MUST NOT be returned on non-extensible
103 ; "BODY" fetch
104
105
106 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
107 *(SP body-extension)]]
108 ; MUST NOT be returned on non-extensible
109 ; "BODY" fetch
110
111 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
112 body-fld-enc SP body-fld-octets
113
114 body-fld-desc = nstring
115
116 body-fld-dsp = "(" string SP body-fld-param ")" / nil
117
118 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
119 "QUOTED-PRINTABLE") DQUOTE) / string
120
121 body-fld-id = nstring
122
123 body-fld-lang = nstring / "(" string *(SP string) ")"
124
125 body-fld-lines = number
126
127 body-fld-md5 = nstring
128
129 body-fld-octets = number
130
131 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
132
133 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
134 [SP body-ext-1part]
135
136 body-type-basic = media-basic SP body-fields
137 ; MESSAGE subtype MUST NOT be "RFC822"
138
139 body-type-mpart = 1*body SP media-subtype
140 [SP body-ext-mpart]
141
142 body-type-msg = media-message SP body-fields SP envelope
143 SP body SP body-fld-lines
144
145 body-type-text = media-text SP body-fields SP body-fld-lines
146
147 capability = ("AUTH=" auth-type) / atom
148 ; New capabilities MUST begin with "X" or be
149 ; registered with IANA as standard or
150 ; standards-track
151
152
153 capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
154 *(SP capability)
155 ; IMAP4rev1 servers which offer RFC 1730
156 ; compatibility MUST list "IMAP4" as the first
157 ; capability.
158
159 CHAR8 = %x01-ff
160 ; any OCTET except NUL, %x00
161
162 command = tag SP (command-any / command-auth / command-nonauth /
163 command-select) CRLF
164 ; Modal based on state
165
166 command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
167 ; Valid in all states
168
169 command-auth = append / create / delete / examine / list / lsub /
170 rename / select / status / subscribe / unsubscribe
171 ; Valid only in Authenticated or Selected state
172
173 command-nonauth = login / authenticate
174 ; Valid only when in Not Authenticated state
175
176 command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
177 uid / search
178 ; Valid only when in Selected state
179
180 continue-req = "+" SP (resp-text / base64) CRLF
181
182 copy = "COPY" SP set SP mailbox
183
184 create = "CREATE" SP mailbox
185 ; Use of INBOX gives a NO error
186
187 date = date-text / DQUOTE date-text DQUOTE
188
189 date-day = 1*2DIGIT
190 ; Day of month
191
192 date-day-fixed = (SP DIGIT) / 2DIGIT
193 ; Fixed-format version of date-day
194
195 date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
196 "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
197
198 date-text = date-day "-" date-month "-" date-year
199
200 date-year = 4DIGIT
201
202 date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
203 SP time SP zone DQUOTE
204
205 delete = "DELETE" SP mailbox
206 ; Use of INBOX gives a NO error
207
208 digit-nz = %x31-39
209 ; 1-9
210
211 envelope = "(" env-date SP env-subject SP env-from SP env-sender SP
212 env-reply-to SP env-to SP env-cc SP env-bcc SP
213 env-in-reply-to SP env-message-id ")"
214
215 env-bcc = "(" 1*address ")" / nil
216
217 env-cc = "(" 1*address ")" / nil
218
219 env-date = nstring
220
221 env-from = "(" 1*address ")" / nil
222
223 env-in-reply-to = nstring
224
225 env-message-id = nstring
226
227 env-reply-to = "(" 1*address ")" / nil
228
229 env-sender = "(" 1*address ")" / nil
230
231 env-subject = nstring
232
233 env-to = "(" 1*address ")" / nil
234
235 examine = "EXAMINE" SP mailbox
236
237 fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att /
238 "(" fetch-att *(SP fetch-att) ")")
239
240 fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
241 "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
242 "BODY" ["STRUCTURE"] / "UID" /
243 "BODY" [".PEEK"] section ["<" number "." nz-number ">"]
244
245 flag = "\Answered" / "\Flagged" / "\Deleted" /
246 "\Seen" / "\Draft" / flag-keyword / flag-extension
247 ; Does not include "\Recent"
248
249 flag-extension = "\" atom
250 ; Future expansion. Client implementations
251 ; MUST accept flag-extension flags. Server
252 ; implementations MUST NOT generate
253 ; flag-extension flags except as defined by
254 ; future standard or standards-track
255 ; revisions of this specification.
256
257 flag-fetch = flag / "\Recent"
258
259 flag-keyword = atom
260
261 flag-list = "(" [flag *(SP flag)] ")"
262
263 flag-perm = flag / "\*"
264
265 greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
266
267 header-fld-name = astring
268
269 header-list = "(" header-fld-name *(SP header-fld-name) ")"
270
271 list = "LIST" SP mailbox SP list-mailbox
272
273 list-mailbox = 1*list-char / string
274
275 list-char = ATOM-CHAR / list-wildcards / resp-specials
276
277 list-wildcards = "%" / "*"
278
279 literal = "{" number "}" CRLF *CHAR8
280 ; Number represents the number of CHAR8s
281
282 login = "LOGIN" SP userid SP password
283
284 lsub = "LSUB" SP mailbox SP list-mailbox
285
286 mailbox = "INBOX" / astring
287 ; INBOX is case-insensitive. All case variants of
288 ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
289 ; not as an astring. An astring which consists of
290 ; the case-insensitive sequence "I" "N" "B" "O" "X"
291 ; is considered to be INBOX and not an astring.
292 ; Refer to section 5.1 for further
293 ; semantic details of mailbox names.
294
295 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
296 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
297 "STATUS" SP mailbox SP "("
298 [status-att SP number *(SP status-att SP number)] ")" /
299 number SP "EXISTS" / number SP "RECENT"
300
301 mailbox-list = "(" [mbx-list-flags] ")" SP
302 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
303
304 mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
305 *(SP mbx-list-oflag) /
306 mbx-list-oflag *(SP mbx-list-oflag)
307
308 mbx-list-oflag = "\Noinferiors" / flag-extension
309 ; Other flags; multiple possible per LIST response
310
311 mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
312 ; Selectability flags; only one per LIST response
313
314 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
315 "VIDEO") DQUOTE) / string) SP media-subtype
316 ; Defined in [MIME-IMT]
317
318 media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
319 ; Defined in [MIME-IMT]
320
321 media-subtype = string
322 ; Defined in [MIME-IMT]
323
324 media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
325 ; Defined in [MIME-IMT]
326
327 message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
328
329 msg-att = "(" (msg-att-dynamic / msg-att-static)
330 *(SP (msg-att-dynamic / msg-att-static)) ")"
331
332 msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
333 ; MAY change for a message
334
335 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
336 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
337 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
338 "BODY" section ["<" number ">"] SP nstring /
339 "UID" SP uniqueid
340 ; MUST NOT change for a message
341
342 nil = "NIL"
343
344 nstring = string / nil
345
346 number = 1*DIGIT
347 ; Unsigned 32-bit integer
348 ; (0 <= n < 4,294,967,296)
349
350 nz-number = digit-nz *DIGIT
351 ; Non-zero unsigned 32-bit integer
352 ; (0 < n < 4,294,967,296)
353
354 password = astring
355
356 quoted = DQUOTE *QUOTED-CHAR DQUOTE
357
358 QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
359 "\" quoted-specials
360
361 quoted-specials = DQUOTE / "\"
362
363 rename = "RENAME" SP mailbox SP mailbox
364 ; Use of INBOX as a destination gives a NO error
365
366 response = *(continue-req / response-data) response-done
367
368 response-data = "*" SP (resp-cond-state / resp-cond-bye /
369 mailbox-data / message-data / capability-data) CRLF
370
371 response-done = response-tagged / response-fatal
372
373 response-fatal = "*" SP resp-cond-bye CRLF
374 ; Server closes connection immediately
375
376 response-tagged = tag SP resp-cond-state CRLF
377
378 resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
379 ; Authentication condition
380
381 resp-cond-bye = "BYE" SP resp-text
382
383 resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
384 ; Status condition
385
386 resp-specials = "]"
387
388 resp-text = ["[" resp-text-code "]" SP] text
389
390 resp-text-code = "ALERT" /
391 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
392 capability-data / "PARSE" /
393 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
394 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
395 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
396 "UNSEEN" SP nz-number /
397 atom [SP 1*<any TEXT-CHAR except "]">]
398
399 search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
400 ; CHARSET argument to MUST be registered with IANA
401
402 search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
403 "BEFORE" SP date / "BODY" SP astring /
404 "CC" SP astring / "DELETED" / "FLAGGED" /
405 "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" /
406 "OLD" / "ON" SP date / "RECENT" / "SEEN" /
407 "SINCE" SP date / "SUBJECT" SP astring /
408 "TEXT" SP astring / "TO" SP astring /
409 "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
410 "UNKEYWORD" SP flag-keyword / "UNSEEN" /
411 ; Above this line were in [IMAP2]
412 "DRAFT" / "HEADER" SP header-fld-name SP astring /
413 "LARGER" SP number / "NOT" SP search-key /
414 "OR" SP search-key SP search-key /
415 "SENTBEFORE" SP date / "SENTON" SP date /
416 "SENTSINCE" SP date / "SMALLER" SP number /
417 "UID" SP set / "UNDRAFT" / set /
418 "(" search-key *(SP search-key) ")"
419
420 section = "[" [section-spec] "]"
421
422 section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
423 "TEXT"
424 ; top-level or MESSAGE/RFC822 part
425
426 section-part = nz-number *("." nz-number)
427 ; body part nesting
428
429 section-spec = section-msgtext / (section-part ["." section-text])
430
431 section-text = section-msgtext / "MIME"
432 ; text other than actual body part (headers, etc.)
433
434 select = "SELECT" SP mailbox
435
436 sequence-num = nz-number / "*"
437 ; * is the largest number in use. For message
438 ; sequence numbers, it is the number of messages
439 ; in the mailbox. For unique identifiers, it is
440 ; the unique identifier of the last message in
441 ; the mailbox.
442
443 set = sequence-num / (sequence-num ":" sequence-num) /
444 (set "," set)
445 ; Identifies a set of messages. For message
446 ; sequence numbers, these are consecutive
447 ; numbers from 1 to the number of messages in
448 ; the mailbox
449 ; Comma delimits individual numbers, colon
450 ; delimits between two numbers inclusive.
451 ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
452 ; 14,15 for a mailbox with 15 messages.
453
454
455 status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
456
457 status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
458 "UNSEEN"
459
460 store = "STORE" SP set SP store-att-flags
461
462 store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
463 (flag-list / (flag *(SP flag)))
464
465 string = quoted / literal
466
467 subscribe = "SUBSCRIBE" SP mailbox
468
469 tag = 1*<any ASTRING-CHAR except "+">
470
471 text = 1*TEXT-CHAR
472
473 TEXT-CHAR = <any CHAR except CR and LF>
474
475 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
476 ; Hours minutes seconds
477
478 uid = "UID" SP (copy / fetch / search / store)
479 ; Unique identifiers used instead of message
480 ; sequence numbers
481
482 uniqueid = nz-number
483 ; Strictly ascending
484
485 unsubscribe = "UNSUBSCRIBE" SP mailbox
486
487 userid = astring
488
489 x-command = "X" atom <experimental command arguments>
490
491 zone = ("+" / "-") 4DIGIT
492 ; Signed four-digit value of hhmm representing
493 ; hours and minutes east of Greenwich (that is,
494 ; the amount that the given time differs from
495 ; Universal Time). Subtracting the timezone
496 ; from the given time will give the UT form.
497 ; The Universal Time zone is "+0000".
498*/
499
500
501#ifndef MAILIMAP_TYPES_H
502
503#define MAILIMAP_TYPES_H
504
505#ifdef __cplusplus
506extern "C" {
507#endif
508
509#include <inttypes.h>
510#include <libetpan/mailstream.h>
511#include <libetpan/clist.h>
512
513
514/*
515 IMPORTANT NOTE:
516
517 All allocation functions will take as argument allocated data
518 and will store these data in the structure they will allocate.
519 Data should be persistant during all the use of the structure
520 and will be freed by the free function of the structure
521
522 allocation functions will return NULL on failure
523*/
524
525
526/*
527 mailimap_address represents a mail address
528
529 - personal_name is the name to display in an address
530 '"name"' in '"name" <address@domain>', should be allocated
531 with a malloc()
532
533 - source_route is the source-route information in the
534 mail address (RFC 822), should be allocated with a malloc()
535
536 - mailbox_name is the name of the mailbox 'address' in
537 '"name" <address@domain>', should be allocated with a malloc()
538
539 - host_name is the name of the host 'domain' in
540 '"name" <address@domain>', should be allocated with a malloc()
541
542 if mailbox_name is not NULL and host_name is NULL, this is the name
543 of a group, the next addresses in the list are elements of the group
544 until we reach an address with a NULL mailbox_name.
545*/
546
547struct mailimap_address {
548 char * ad_personal_name; /* can be NULL */
549 char * ad_source_route; /* can be NULL */
550 char * ad_mailbox_name; /* can be NULL */
551 char * ad_host_name; /* can be NULL */
552};
553
554
555struct mailimap_address *
556mailimap_address_new(char * ad_personal_name, char * ad_source_route,
557 char * ad_mailbox_name, char * ad_host_name);
558
559void mailimap_address_free(struct mailimap_address * addr);
560
561
562/* this is the type of MIME body parsed by IMAP server */
563
564enum {
565 MAILIMAP_BODY_ERROR,
566 MAILIMAP_BODY_1PART, /* single part */
567 MAILIMAP_BODY_MPART, /* multi-part */
568};
569
570/*
571 mailimap_body represent a MIME body parsed by IMAP server
572
573 - type is the type of the MIME part (single part or multipart)
574
575 - body_1part is defined if this is a single part
576
577 - body_mpart is defined if this is a multipart
578*/
579
580struct mailimap_body {
581 int bd_type;
582 /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */
583 union {
584 struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */
585 struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */
586 } bd_data;
587};
588
589
590struct mailimap_body *
591mailimap_body_new(int bd_type,
592 struct mailimap_body_type_1part * bd_body_1part,
593 struct mailimap_body_type_mpart * bd_body_mpart);
594
595void mailimap_body_free(struct mailimap_body * body);
596
597
598
599/*
600 this is the type of MIME body extension
601*/
602
603enum {
604 MAILIMAP_BODY_EXTENSION_ERROR,
605 MAILIMAP_BODY_EXTENSION_NSTRING, /* string */
606 MAILIMAP_BODY_EXTENSION_NUMBER, /* number */
607 MAILIMAP_BODY_EXTENSION_LIST, /* list of
608 (struct mailimap_body_extension *) */
609};
610
611/*
612 mailimap_body_extension is a future extension header field value
613
614 - type is the type of the body extension (string, number or
615 list of extension)
616
617 - nstring is a string value if the type is string
618
619 - number is a integer value if the type is number
620
621 - list is a list of body extension if the type is a list
622*/
623
624struct mailimap_body_extension {
625 int ext_type;
626 /*
627 can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER
628 or MAILIMAP_BODY_EXTENSION_LIST
629 */
630 union {
631 char * ext_nstring; /* can be NULL */
632 uint32_t ext_number;
633 clist * ext_body_extension_list;
634 /* list of (struct mailimap_body_extension *) */
635 /* can be NULL */
636 } ext_data;
637};
638
639struct mailimap_body_extension *
640mailimap_body_extension_new(int ext_type, char * ext_nstring,
641 uint32_t ext_number,
642 clist * ext_body_extension_list);
643
644void mailimap_body_extension_free(struct mailimap_body_extension * be);
645
646
647/*
648 mailimap_body_ext_1part is the extended result part of a single part
649 bodystructure.
650
651 - body_md5 is the value of the Content-MD5 header field, should be
652 allocated with malloc()
653
654 - body_disposition is the value of the Content-Disposition header field
655
656 - body_language is the value of the Content-Language header field
657
658 - body_extension_list is the list of extension fields value.
659*/
660
661struct mailimap_body_ext_1part {
662 char * bd_md5; /* != NULL */
663 struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */
664 struct mailimap_body_fld_lang * bd_language; /* can be NULL */
665
666 clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */
667 /* can be NULL */
668};
669
670struct mailimap_body_ext_1part *
671mailimap_body_ext_1part_new(char * bd_md5,
672 struct mailimap_body_fld_dsp * bd_disposition,
673 struct mailimap_body_fld_lang * bd_language,
674 clist * bd_extension_list);
675
676
677void
678mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part);
679
680
681/*
682 mailimap_body_ext_mpart is the extended result part of a multipart
683 bodystructure.
684
685 - body_parameter is the list of parameters of Content-Type header field
686
687 - body_disposition is the value of Content-Disposition header field
688
689 - body_language is the value of Content-Language header field
690
691 - body_extension_list is the list of extension fields value.
692*/
693
694struct mailimap_body_ext_mpart {
695 struct mailimap_body_fld_param * bd_parameter; /* != NULL */
696 struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */
697 struct mailimap_body_fld_lang * bd_language; /* can be NULL */
698 clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */
699 /* can be NULL */
700};
701
702struct mailimap_body_ext_mpart *
703mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter,
704 struct mailimap_body_fld_dsp * bd_disposition,
705 struct mailimap_body_fld_lang * bd_language,
706 clist * bd_extension_list);
707
708void
709mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart);
710
711
712/*
713 mailimap_body_fields is the MIME fields of a MIME part.
714
715 - body_parameter is the list of parameters of Content-Type header field
716
717 - body_id is the value of Content-ID header field, should be allocated
718 with malloc()
719
720 - body_description is the value of Content-Description header field,
721 should be allocated with malloc()
722
723 - body_encoding is the value of Content-Transfer-Encoding header field
724
725 - body_disposition is the value of Content-Disposition header field
726
727 - body_size is the size of the MIME part
728*/
729
730struct mailimap_body_fields {
731 struct mailimap_body_fld_param * bd_parameter; /* != NULL */
732 char * bd_id; /* can be NULL */
733 char * bd_description; /* can be NULL */
734 struct mailimap_body_fld_enc * bd_encoding; /* != NULL */
735 uint32_t bd_size;
736};
737
738struct mailimap_body_fields *
739mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter,
740 char * bd_id,
741 char * bd_description,
742 struct mailimap_body_fld_enc * bd_encoding,
743 uint32_t bd_size);
744
745void
746mailimap_body_fields_free(struct mailimap_body_fields * body_fields);
747
748
749
750/*
751 mailimap_body_fld_dsp is the parsed value of the Content-Disposition field
752
753 - disposition_type is the type of Content-Disposition
754 (usually attachment or inline), should be allocated with malloc()
755
756 - attributes is the list of Content-Disposition attributes
757*/
758
759struct mailimap_body_fld_dsp {
760 char * dsp_type; /* != NULL */
761 struct mailimap_body_fld_param * dsp_attributes; /* != NULL */
762};
763
764struct mailimap_body_fld_dsp *
765mailimap_body_fld_dsp_new(char * dsp_type,
766 struct mailimap_body_fld_param * dsp_attributes);
767
768void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd);
769
770
771
772/* these are the different parsed values for Content-Transfer-Encoding */
773
774enum {
775 MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */
776 MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */
777 MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */
778 MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */
779 MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */
780 MAILIMAP_BODY_FLD_ENC_OTHER, /* other */
781};
782
783/*
784 mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding
785
786 - type is the kind of Content-Transfer-Encoding, this can be
787 MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT,
788 MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64,
789 MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER
790
791 - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined,
792 should be allocated with malloc()
793*/
794
795struct mailimap_body_fld_enc {
796 int enc_type;
797 char * enc_value; /* can be NULL */
798};
799
800struct mailimap_body_fld_enc *
801mailimap_body_fld_enc_new(int enc_type, char * enc_value);
802
803void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe);
804
805
806/* this is the type of Content-Language header field value */
807
808enum {
809 MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */
810 MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */
811 MAILIMAP_BODY_FLD_LANG_LIST /* list of values */
812};
813
814/*
815 mailimap_body_fld_lang is the parsed value of the Content-Language field
816
817 - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE
818 if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are
819 several values
820
821 - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE,
822 should be allocated with malloc()
823
824 - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST,
825 all elements of the list should be allocated with malloc()
826*/
827
828struct mailimap_body_fld_lang {
829 int lg_type;
830 union {
831 char * lg_single; /* can be NULL */
832 clist * lg_list; /* list of string (char *), can be NULL */
833 } lg_data;
834};
835
836struct mailimap_body_fld_lang *
837mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list);
838
839void
840mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang);
841
842
843
844/*
845 mailimap_single_body_fld_param is a body field parameter
846
847 - name is the name of the parameter, should be allocated with malloc()
848
849 - value is the value of the parameter, should be allocated with malloc()
850*/
851
852struct mailimap_single_body_fld_param {
853 char * pa_name; /* != NULL */
854 char * pa_value; /* != NULL */
855};
856
857struct mailimap_single_body_fld_param *
858mailimap_single_body_fld_param_new(char * pa_name, char * pa_value);
859
860void
861mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p);
862
863
864/*
865 mailmap_body_fld_param is a list of parameters
866
867 - list is the list of parameters.
868*/
869
870struct mailimap_body_fld_param {
871 clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */
872 /* != NULL */
873};
874
875struct mailimap_body_fld_param *
876mailimap_body_fld_param_new(clist * pa_list);
877
878void
879mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param);
880
881
882/*
883 this is the kind of single part: a text part
884 (when Content-Type is text/xxx), a message part (when Content-Type is
885 message/rfc2822) or a basic part (others than multpart/xxx)
886*/
887
888enum {
889 MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */
890 MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */
891 MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */
892 MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */
893};
894
895
896/*
897 mailimap_body_type_1part is
898
899 - type is the kind of single part, this can be
900 MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or
901 MAILIMAP_BODY_TYPE_1PART_TEXT.
902
903 - body_type_basic is the basic part when type is
904 MAILIMAP_BODY_TYPE_1PART_BASIC
905
906 - body_type_msg is the message part when type is
907 MAILIMAP_BODY_TYPE_1PART_MSG
908
909 - body_type_text is the text part when type is
910 MAILIMAP_BODY_TYPE_1PART_TEXT
911*/
912
913struct mailimap_body_type_1part {
914 int bd_type;
915 union {
916 struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */
917 struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */
918 struct mailimap_body_type_text * bd_type_text; /* can be NULL */
919 } bd_data;
920 struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */
921};
922
923struct mailimap_body_type_1part *
924mailimap_body_type_1part_new(int bd_type,
925 struct mailimap_body_type_basic * bd_type_basic,
926 struct mailimap_body_type_msg * bd_type_msg,
927 struct mailimap_body_type_text * bd_type_text,
928 struct mailimap_body_ext_1part * bd_ext_1part);
929
930void
931mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p);
932
933
934
935/*
936 mailimap_body_type_basic is a basic field (with Content-Type other
937 than multipart/xxx, message/rfc2822 and text/xxx
938
939 - media_basic will be the MIME type of the part
940
941 - body_fields will be the parsed fields of the MIME part
942*/
943
944struct mailimap_body_type_basic {
945 struct mailimap_media_basic * bd_media_basic; /* != NULL */
946 struct mailimap_body_fields * bd_fields; /* != NULL */
947};
948
949struct mailimap_body_type_basic *
950mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic,
951 struct mailimap_body_fields * bd_fields);
952
953void mailimap_body_type_basic_free(struct mailimap_body_type_basic *
954 body_type_basic);
955
956/*
957 mailimap_body_type_mpart is a MIME multipart.
958
959 - body_list is the list of sub-parts.
960
961 - media_subtype is the subtype of the multipart (for example
962 in multipart/alternative, this is "alternative")
963
964 - body_ext_mpart is the extended fields of the MIME multipart
965*/
966
967struct mailimap_body_type_mpart {
968 clist * bd_list; /* list of (struct mailimap_body *) */
969 /* != NULL */
970 char * bd_media_subtype; /* != NULL */
971 struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */
972};
973
974struct mailimap_body_type_mpart *
975mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype,
976 struct mailimap_body_ext_mpart * bd_ext_mpart);
977
978void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart *
979 body_type_mpart);
980
981/*
982 mailimap_body_type_msg is a MIME message part
983
984 - body_fields is the MIME fields of the MIME message part
985
986 - envelope is the list of parsed RFC 822 fields of the MIME message
987
988 - body is the sub-part of the message
989
990 - body_lines is the number of lines of the message part
991*/
992
993struct mailimap_body_type_msg {
994 struct mailimap_body_fields * bd_fields; /* != NULL */
995 struct mailimap_envelope * bd_envelope; /* != NULL */
996 struct mailimap_body * bd_body; /* != NULL */
997 uint32_t bd_lines;
998};
999
1000struct mailimap_body_type_msg *
1001mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields,
1002 struct mailimap_envelope * bd_envelope,
1003 struct mailimap_body * bd_body,
1004 uint32_t bd_lines);
1005
1006void
1007mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg);
1008
1009
1010
1011/*
1012 mailimap_body_type_text is a single MIME part where Content-Type is text/xxx
1013
1014 - media-text is the subtype of the text part (for example, in "text/plain",
1015 this is "plain", should be allocated with malloc()
1016
1017 - body_fields is the MIME fields of the MIME message part
1018
1019 - body_lines is the number of lines of the message part
1020*/
1021
1022struct mailimap_body_type_text {
1023 char * bd_media_text; /* != NULL */
1024 struct mailimap_body_fields * bd_fields; /* != NULL */
1025 uint32_t bd_lines;
1026};
1027
1028struct mailimap_body_type_text *
1029mailimap_body_type_text_new(char * bd_media_text,
1030 struct mailimap_body_fields * bd_fields,
1031 uint32_t bd_lines);
1032
1033void
1034mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text);
1035
1036
1037
1038/* this is the type of capability field */
1039
1040enum {
1041 MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an
1042 authentication type */
1043 MAILIMAP_CAPABILITY_NAME, /* other type of capability */
1044};
1045
1046/*
1047 mailimap_capability is a capability of the IMAP server
1048
1049 - type is the type of capability, this is either a authentication type
1050 (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability
1051 (MAILIMAP_CAPABILITY_NAME)
1052
1053 - auth_type is a type of authentication "name" in "AUTH=name",
1054 auth_type can be for example "PLAIN", when this is an authentication type,
1055 should be allocated with malloc()
1056
1057 - name is a type of capability when this is not an authentication type,
1058 should be allocated with malloc()
1059*/
1060
1061struct mailimap_capability {
1062 int cap_type;
1063 union {
1064 char * cap_auth_type; /* can be NULL */
1065 char * cap_name; /* can be NULL */
1066 } cap_data;
1067};
1068
1069struct mailimap_capability *
1070mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name);
1071
1072void mailimap_capability_free(struct mailimap_capability * c);
1073
1074
1075
1076
1077/*
1078 mailimap_capability_data is a list of capability
1079
1080 - list is the list of capability
1081*/
1082
1083struct mailimap_capability_data {
1084 clist * cap_list; /* list of (struct mailimap_capability *), != NULL */
1085};
1086
1087struct mailimap_capability_data *
1088mailimap_capability_data_new(clist * cap_list);
1089
1090void
1091mailimap_capability_data_free(struct mailimap_capability_data * cap_data);
1092
1093
1094
1095/* this is the type of continue request data */
1096
1097enum {
1098 MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */
1099 MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */
1100 MAILIMAP_CONTINUE_REQ_BASE64, /* when data is a base64 response */
1101};
1102
1103/*
1104 mailimap_continue_req is a continue request (a response prefixed by "+")
1105
1106 - type is the type of continue request response
1107 MAILIMAP_CONTINUE_REQ_TEXT (when information data is text),
1108 MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64)
1109
1110 - text is the information of type text in case of text data
1111
1112 - base64 is base64 encoded data in the other case, should be allocated
1113 with malloc()
1114*/
1115
1116struct mailimap_continue_req {
1117 int cr_type;
1118 union {
1119 struct mailimap_resp_text * cr_text; /* can be NULL */
1120 char * cr_base64; /* can be NULL */
1121 } cr_data;
1122};
1123
1124struct mailimap_continue_req *
1125mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text,
1126 char * cr_base64);
1127
1128void mailimap_continue_req_free(struct mailimap_continue_req * cont_req);
1129
1130
1131/*
1132 mailimap_date_time is a date
1133
1134 - day is the day of month (1 to 31)
1135
1136 - month (1 to 12)
1137
1138 - year (4 digits)
1139
1140 - hour (0 to 23)
1141
1142 - min (0 to 59)
1143
1144 - sec (0 to 59)
1145
1146 - zone (this is the decimal value that we can read, for example:
1147 for "-0200", the value is -200)
1148*/
1149
1150struct mailimap_date_time {
1151 int dt_day;
1152 int dt_month;
1153 int dt_year;
1154 int dt_hour;
1155 int dt_min;
1156 int dt_sec;
1157 int dt_zone;
1158};
1159
1160struct mailimap_date_time *
1161mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour,
1162 int dt_min, int dt_sec, int dt_zone);
1163
1164void mailimap_date_time_free(struct mailimap_date_time * date_time);
1165
1166
1167
1168/*
1169 mailimap_envelope is the list of fields that can be parsed by
1170 the IMAP server.
1171
1172 - date is the (non-parsed) content of the "Date" header field,
1173 should be allocated with malloc()
1174
1175 - subject is the subject of the message, should be allocated with
1176 malloc()
1177
1178 - sender is the the parsed content of the "Sender" field
1179
1180 - reply-to is the parsed content of the "Reply-To" field
1181
1182 - to is the parsed content of the "To" field
1183
1184 - cc is the parsed content of the "Cc" field
1185
1186 - bcc is the parsed content of the "Bcc" field
1187
1188 - in_reply_to is the content of the "In-Reply-To" field,
1189 should be allocated with malloc()
1190
1191 - message_id is the content of the "Message-ID" field,
1192 should be allocated with malloc()
1193*/
1194
1195struct mailimap_envelope {
1196 char * env_date; /* can be NULL */
1197 char * env_subject; /* can be NULL */
1198 struct mailimap_env_from * env_from; /* can be NULL */
1199 struct mailimap_env_sender * env_sender; /* can be NULL */
1200 struct mailimap_env_reply_to * env_reply_to; /* can be NULL */
1201 struct mailimap_env_to * env_to; /* can be NULL */
1202 struct mailimap_env_cc * env_cc; /* can be NULL */
1203 struct mailimap_env_bcc * env_bcc; /* can be NULL */
1204 char * env_in_reply_to; /* can be NULL */
1205 char * env_message_id; /* can be NULL */
1206};
1207
1208struct mailimap_envelope *
1209mailimap_envelope_new(char * env_date, char * env_subject,
1210 struct mailimap_env_from * env_from,
1211 struct mailimap_env_sender * env_sender,
1212 struct mailimap_env_reply_to * env_reply_to,
1213 struct mailimap_env_to * env_to,
1214 struct mailimap_env_cc* env_cc,
1215 struct mailimap_env_bcc * env_bcc,
1216 char * env_in_reply_to, char * env_message_id);
1217
1218void mailimap_envelope_free(struct mailimap_envelope * env);
1219
1220
1221
1222/*
1223 mailimap_env_bcc is the parsed "Bcc" field
1224
1225 - list is the list of addresses
1226*/
1227
1228struct mailimap_env_bcc {
1229 clist * bcc_list; /* list of (struct mailimap_address *), != NULL */
1230};
1231
1232struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list);
1233
1234void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc);
1235
1236
1237/*
1238 mailimap_env_cc is the parsed "Cc" field
1239
1240 - list is the list of addresses
1241*/
1242
1243struct mailimap_env_cc {
1244 clist * cc_list; /* list of (struct mailimap_address *), != NULL */
1245};
1246
1247struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list);
1248
1249void mailimap_env_cc_free(struct mailimap_env_cc * env_cc);
1250
1251
1252
1253/*
1254 mailimap_env_from is the parsed "From" field
1255
1256 - list is the list of addresses
1257*/
1258
1259struct mailimap_env_from {
1260 clist * frm_list; /* list of (struct mailimap_address *) */
1261 /* != NULL */
1262};
1263
1264struct mailimap_env_from * mailimap_env_from_new(clist * frm_list);
1265
1266void mailimap_env_from_free(struct mailimap_env_from * env_from);
1267
1268
1269
1270/*
1271 mailimap_env_reply_to is the parsed "Reply-To" field
1272
1273 - list is the list of addresses
1274*/
1275
1276struct mailimap_env_reply_to {
1277 clist * rt_list; /* list of (struct mailimap_address *), != NULL */
1278};
1279
1280struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list);
1281
1282void
1283mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to);
1284
1285
1286
1287/*
1288 mailimap_env_sender is the parsed "Sender" field
1289
1290 - list is the list of addresses
1291*/
1292
1293struct mailimap_env_sender {
1294 clist * snd_list; /* list of (struct mailimap_address *), != NULL */
1295};
1296
1297struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list);
1298
1299void mailimap_env_sender_free(struct mailimap_env_sender * env_sender);
1300
1301
1302
1303/*
1304 mailimap_env_to is the parsed "To" field
1305
1306 - list is the list of addresses
1307*/
1308
1309struct mailimap_env_to {
1310 clist * to_list; /* list of (struct mailimap_address *), != NULL */
1311};
1312
1313struct mailimap_env_to * mailimap_env_to_new(clist * to_list);
1314
1315void mailimap_env_to_free(struct mailimap_env_to * env_to);
1316
1317
1318/* this is the type of flag */
1319
1320enum {
1321 MAILIMAP_FLAG_ANSWERED, /* \Answered flag */
1322 MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */
1323 MAILIMAP_FLAG_DELETED, /* \Deleted flag */
1324 MAILIMAP_FLAG_SEEN, /* \Seen flag */
1325 MAILIMAP_FLAG_DRAFT, /* \Draft flag */
1326 MAILIMAP_FLAG_KEYWORD, /* keyword flag */
1327 MAILIMAP_FLAG_EXTENSION, /* \extension flag */
1328};
1329
1330
1331/*
1332 mailimap_flag is a message flag (that we can associate with a message)
1333
1334 - type is the type of the flag, MAILIMAP_FLAG_XXX
1335
1336 - keyword is the flag when the flag is of keyword type,
1337 should be allocated with malloc()
1338
1339 - extension is the flag when the flag is of extension type, should be
1340 allocated with malloc()
1341*/
1342
1343struct mailimap_flag {
1344 int fl_type;
1345 union {
1346 char * fl_keyword; /* can be NULL */
1347 char * fl_extension; /* can be NULL */
1348 } fl_data;
1349};
1350
1351struct mailimap_flag * mailimap_flag_new(int fl_type,
1352 char * fl_keyword, char * fl_extension);
1353
1354void mailimap_flag_free(struct mailimap_flag * f);
1355
1356
1357
1358
1359/* this is the type of flag */
1360
1361enum {
1362 MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */
1363 MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */
1364 MAILIMAP_FLAG_FETCH_OTHER, /* other type of flag */
1365};
1366
1367/*
1368 mailimap_flag_fetch is a message flag (when we fetch it)
1369
1370 - type is the type of flag fetch
1371
1372 - flag is the flag when this is not a \Recent flag
1373*/
1374
1375struct mailimap_flag_fetch {
1376 int fl_type;
1377 struct mailimap_flag * fl_flag; /* can be NULL */
1378};
1379
1380struct mailimap_flag_fetch *
1381mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag);
1382
1383void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch);
1384
1385
1386
1387
1388/* this is the type of flag */
1389
1390enum {
1391 MAILIMAP_FLAG_PERM_ERROR, /* on parse error */
1392 MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */
1393 MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */
1394};
1395
1396
1397/*
1398 mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response
1399
1400 - type is the type of returned PERMANENTFLAGS, it can be
1401 MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or
1402 MAILIMAP_FLAG_PERM_ALL (new flags can be created)
1403
1404 - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG
1405*/
1406
1407struct mailimap_flag_perm {
1408 int fl_type;
1409 struct mailimap_flag * fl_flag; /* can be NULL */
1410};
1411
1412struct mailimap_flag_perm *
1413mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag);
1414
1415void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm);
1416
1417
1418/*
1419 mailimap_flag_list is a list of flags
1420
1421 - list is a list of flags
1422*/
1423
1424struct mailimap_flag_list {
1425 clist * fl_list; /* list of (struct mailimap_flag *), != NULL */
1426};
1427
1428struct mailimap_flag_list *
1429mailimap_flag_list_new(clist * fl_list);
1430
1431void mailimap_flag_list_free(struct mailimap_flag_list * flag_list);
1432
1433
1434
1435
1436/* this is the type of greeting response */
1437
1438enum {
1439 MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */
1440 MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */
1441 MAILIMAP_GREETING_RESP_COND_BYE, /* when connection is refused */
1442};
1443
1444/*
1445 mailimap_greeting is the response returned on connection
1446
1447 - type is the type of response on connection, either
1448 MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or
1449 MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused
1450*/
1451
1452struct mailimap_greeting {
1453 int gr_type;
1454 union {
1455 struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */
1456 struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */
1457 } gr_data;
1458};
1459
1460struct mailimap_greeting *
1461mailimap_greeting_new(int gr_type,
1462 struct mailimap_resp_cond_auth * gr_auth,
1463 struct mailimap_resp_cond_bye * gr_bye);
1464
1465void mailimap_greeting_free(struct mailimap_greeting * greeting);
1466
1467
1468/*
1469 mailimap_header_list is a list of headers that can be specified when
1470 we want to fetch fields
1471
1472 - list is a list of header names, each header name should be allocated
1473 with malloc()
1474*/
1475
1476struct mailimap_header_list {
1477 clist * hdr_list; /* list of astring (char *), != NULL */
1478};
1479
1480struct mailimap_header_list *
1481mailimap_header_list_new(clist * hdr_list);
1482
1483void
1484mailimap_header_list_free(struct mailimap_header_list * header_list);
1485
1486
1487
1488/* this is the type of mailbox STATUS that can be returned */
1489
1490enum {
1491 MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of
1492 messages */
1493 MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of
1494 recent messages */
1495 MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique
1496 identifier */
1497 MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of
1498 message unique identifiers*/
1499 MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of
1500 unseen messages */
1501};
1502
1503/*
1504 mailimap_status_info is a returned information when a STATUS of
1505 a mailbox is requested
1506
1507 - att is the type of mailbox STATUS, the value can be
1508 MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT,
1509 MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or
1510 MAILIMAP_STATUS_ATT_UNSEEN
1511
1512 - value is the value of the given information
1513*/
1514
1515struct mailimap_status_info {
1516 int st_att;
1517 uint32_t st_value;
1518};
1519
1520struct mailimap_status_info *
1521mailimap_status_info_new(int st_att, uint32_t st_value);
1522
1523void mailimap_status_info_free(struct mailimap_status_info * info);
1524
1525
1526
1527/*
1528 mailimap_mailbox_data_status is the list of information returned
1529 when a STATUS of a mailbox is requested
1530
1531 - mailbox is the name of the mailbox, should be allocated with malloc()
1532
1533 - status_info_list is the list of information returned
1534*/
1535
1536struct mailimap_mailbox_data_status {
1537 char * st_mailbox;
1538 clist * st_info_list; /* list of (struct mailimap_status_info *) */
1539 /* can be NULL */
1540};
1541
1542struct mailimap_mailbox_data_status *
1543mailimap_mailbox_data_status_new(char * st_mailbox,
1544 clist * st_info_list);
1545
1546void
1547mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info);
1548
1549
1550
1551/* this is the type of mailbox information that is returned */
1552
1553enum {
1554 MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */
1555 MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */
1556 MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes
1557 returned on LIST command*/
1558 MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of
1559 subscribed mailboxes returned on LSUB
1560 command */
1561 MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or
1562 unique identifiers returned
1563 on a SEARCH command*/
1564 MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned
1565 on a STATUS command */
1566 MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the
1567 mailbox */
1568 MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages
1569 in the mailbox */
1570};
1571
1572/*
1573 mailimap_mailbox_data is an information related to a mailbox
1574
1575 - type is the type of mailbox_data that is filled, the value of this field
1576 can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST,
1577 MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH,
1578 MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS
1579 or MAILIMAP_MAILBOX_DATA_RECENT.
1580
1581 - flags is the flags that are applicable to the mailbox when
1582 type is MAILIMAP_MAILBOX_DATA_FLAGS
1583
1584 - list is a mailbox in the list of mailboxes returned on LIST command
1585 when type is MAILIMAP_MAILBOX_DATA_LIST
1586
1587 - lsub is a mailbox in the list of subscribed mailboxes returned on
1588 LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB
1589
1590 - search is a list of messages numbers or unique identifiers returned
1591 on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element
1592 should be allocated with malloc()
1593
1594 - status is a list of information returned on STATUS command when
1595 type is MAILIMAP_MAILBOX_DATA_STATUS
1596
1597 - exists is the number of messages in the mailbox when type
1598 is MAILIMAP_MAILBOX_DATA_EXISTS
1599
1600 - recent is the number of recent messages in the mailbox when type
1601 is MAILIMAP_MAILBOX_DATA_RECENT
1602*/
1603
1604struct mailimap_mailbox_data {
1605 int mbd_type;
1606 union {
1607 struct mailimap_flag_list * mbd_flags; /* can be NULL */
1608 struct mailimap_mailbox_list * mbd_list; /* can be NULL */
1609 struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */
1610 clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */
1611 struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */
1612 uint32_t mbd_exists;
1613 uint32_t mbd_recent;
1614 } mbd_data;
1615};
1616
1617struct mailimap_mailbox_data *
1618mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags,
1619 struct mailimap_mailbox_list * mbd_list,
1620 struct mailimap_mailbox_list * mbd_lsub,
1621 clist * mbd_search,
1622 struct mailimap_mailbox_data_status * mbd_status,
1623 uint32_t mbd_exists,
1624 uint32_t mbd_recent);
1625
1626void
1627mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data);
1628
1629
1630
1631/* this is the type of mailbox flags */
1632
1633enum {
1634 MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in
1635 {\NoSelect, \Marked, \Unmarked} */
1636 MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG, /* mailbox other flag - mailbox flag
1637 other than \NoSelect \Marked and
1638 \Unmarked) */
1639};
1640
1641/* this is a single flag type */
1642
1643enum {
1644 MAILIMAP_MBX_LIST_SFLAG_ERROR,
1645 MAILIMAP_MBX_LIST_SFLAG_MARKED,
1646 MAILIMAP_MBX_LIST_SFLAG_NOSELECT,
1647 MAILIMAP_MBX_LIST_SFLAG_UNMARKED
1648};
1649
1650/*
1651 mailimap_mbx_list_flags is a mailbox flag
1652
1653 - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG,
1654 or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG.
1655
1656 - oflags is a list of "mailbox other flag"
1657
1658 - sflag is a mailbox single flag
1659*/
1660
1661struct mailimap_mbx_list_flags {
1662 int mbf_type;
1663 clist * mbf_oflags; /* list of
1664 (struct mailimap_mbx_list_oflag *), != NULL */
1665 int mbf_sflag;
1666};
1667
1668struct mailimap_mbx_list_flags *
1669mailimap_mbx_list_flags_new(int mbf_type,
1670 clist * mbf_oflags, int mbf_sflag);
1671
1672void
1673mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags);
1674
1675
1676
1677/* this is the type of the mailbox other flag */
1678
1679enum {
1680 MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */
1681 MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */
1682 MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */
1683};
1684
1685/*
1686 mailimap_mbx_list_oflag is a mailbox other flag
1687
1688 - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is
1689 a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT
1690
1691 - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is
1692 an extension flag, should be allocated with malloc()
1693*/
1694
1695struct mailimap_mbx_list_oflag {
1696 int of_type;
1697 char * of_flag_ext; /* can be NULL */
1698};
1699
1700struct mailimap_mbx_list_oflag *
1701mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext);
1702
1703void
1704mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag);
1705
1706
1707
1708/*
1709 mailimap_mailbox_list is a list of mailbox flags
1710
1711 - mb_flag is a list of mailbox flags
1712
1713 - delimiter is the delimiter of the mailbox path
1714
1715 - mb is the name of the mailbox, should be allocated with malloc()
1716*/
1717
1718struct mailimap_mailbox_list {
1719 struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */
1720 char mb_delimiter;
1721 char * mb_name; /* != NULL */
1722};
1723
1724struct mailimap_mailbox_list *
1725mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags,
1726 char mb_delimiter, char * mb_name);
1727
1728void
1729mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list);
1730
1731
1732
1733/* this is the MIME type */
1734
1735enum {
1736 MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */
1737 MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */
1738 MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */
1739 MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */
1740 MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */
1741 MAILIMAP_MEDIA_BASIC_OTHER, /* for all other cases */
1742};
1743
1744
1745/*
1746 mailimap_media_basic is the MIME type
1747
1748 - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO,
1749 MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE,
1750 MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER
1751
1752 - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should
1753 be allocated with malloc()
1754
1755 - subtype is the subtype of the MIME type, for example, this is
1756 "data" in "application/data", should be allocated with malloc()
1757*/
1758
1759struct mailimap_media_basic {
1760 int med_type;
1761 char * med_basic_type; /* can be NULL */
1762 char * med_subtype; /* != NULL */
1763};
1764
1765struct mailimap_media_basic *
1766mailimap_media_basic_new(int med_type,
1767 char * med_basic_type, char * med_subtype);
1768
1769void
1770mailimap_media_basic_free(struct mailimap_media_basic * media_basic);
1771
1772
1773
1774/* this is the type of message data */
1775
1776enum {
1777 MAILIMAP_MESSAGE_DATA_ERROR,
1778 MAILIMAP_MESSAGE_DATA_EXPUNGE,
1779 MAILIMAP_MESSAGE_DATA_FETCH
1780};
1781
1782/*
1783 mailimap_message_data is an information related to a message
1784
1785 - number is the number or the unique identifier of the message
1786
1787 - type is the type of information, this value can be
1788 MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH
1789
1790 - msg_att is the message data
1791*/
1792
1793struct mailimap_message_data {
1794 uint32_t mdt_number;
1795 int mdt_type;
1796 struct mailimap_msg_att * mdt_msg_att; /* can be NULL */
1797 /* if type = EXPUNGE, can be NULL */
1798};
1799
1800struct mailimap_message_data *
1801mailimap_message_data_new(uint32_t mdt_number, int mdt_type,
1802 struct mailimap_msg_att * mdt_msg_att);
1803
1804void
1805mailimap_message_data_free(struct mailimap_message_data * msg_data);
1806
1807
1808
1809/* this the type of the message attributes */
1810
1811enum {
1812 MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */
1813 MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */
1814 MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes
1815 (message content) */
1816};
1817
1818/*
1819 mailimap_msg_att_item is a message attribute
1820
1821 - type is the type of message attribute, the value can be
1822 MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC
1823
1824 - msg_att_dyn is a dynamic message attribute when type is
1825 MAILIMAP_MSG_ATT_ITEM_DYNAMIC
1826
1827 - msg_att_static is a static message attribute when type is
1828 MAILIMAP_MSG_ATT_ITEM_STATIC
1829*/
1830
1831struct mailimap_msg_att_item {
1832 int att_type;
1833 union {
1834 struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */
1835 struct mailimap_msg_att_static * att_static; /* can be NULL */
1836 } att_data;
1837};
1838
1839struct mailimap_msg_att_item *
1840mailimap_msg_att_item_new(int att_type,
1841 struct mailimap_msg_att_dynamic * att_dyn,
1842 struct mailimap_msg_att_static * att_static);
1843
1844void
1845mailimap_msg_att_item_free(struct mailimap_msg_att_item * item);
1846
1847
1848/*
1849 mailimap_msg_att is a list of attributes
1850
1851 - list is a list of message attributes
1852
1853 - number is the message number or unique identifier, this field
1854 has been added for implementation purpose
1855*/
1856
1857struct mailimap_msg_att {
1858 clist * att_list; /* list of (struct mailimap_msg_att_item *) */
1859 /* != NULL */
1860 uint32_t att_number; /* extra field to store the message number,
1861 used for mailimap */
1862};
1863
1864struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list);
1865
1866void mailimap_msg_att_free(struct mailimap_msg_att * msg_att);
1867
1868
1869/*
1870 mailimap_msg_att_dynamic is a dynamic message attribute
1871
1872 - list is a list of flags (that have been fetched)
1873*/
1874
1875struct mailimap_msg_att_dynamic {
1876 clist * att_list; /* list of (struct mailimap_flag_fetch *) */
1877 /* can be NULL */
1878};
1879
1880struct mailimap_msg_att_dynamic *
1881mailimap_msg_att_dynamic_new(clist * att_list);
1882
1883void
1884mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn);
1885
1886
1887
1888/*
1889 mailimap_msg_att_body_section is a MIME part content
1890
1891 - section is the location of the MIME part in the message
1892
1893 - origin_octet is the offset of the requested part of the MIME part
1894
1895 - body_part is the content or partial content of the MIME part,
1896 should be allocated through a MMAPString
1897
1898 - length is the size of the content
1899*/
1900
1901struct mailimap_msg_att_body_section {
1902 struct mailimap_section * sec_section; /* != NULL */
1903 uint32_t sec_origin_octet;
1904 char * sec_body_part; /* can be NULL */
1905 size_t sec_length;
1906};
1907
1908struct mailimap_msg_att_body_section *
1909mailimap_msg_att_body_section_new(struct mailimap_section * section,
1910 uint32_t sec_origin_octet,
1911 char * sec_body_part,
1912 size_t sec_length);
1913
1914void
1915mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section *
1916 msg_att_body_section);
1917
1918
1919
1920/*
1921 this is the type of static message attribute
1922*/
1923
1924enum {
1925 MAILIMAP_MSG_ATT_ERROR, /* on parse error */
1926 MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be
1927 parsed by the server */
1928 MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept
1929 by the server */
1930 MAILIMAP_MSG_ATT_RFC822, /* this is the message content
1931 (header and body) */
1932 MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */
1933 MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */
1934 MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */
1935 MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of
1936 the message */
1937 MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the
1938 message with additional information */
1939 MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */
1940 MAILIMAP_MSG_ATT_UID, /* this is the message unique identifier */
1941};
1942
1943/*
1944 mailimap_msg_att_static is a given part of the message
1945
1946 - type is the type of the static message attribute, the value can be
1947 MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE,
1948 MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER,
1949 MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE,
1950 MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE,
1951 MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID
1952
1953 - env is the headers parsed by the server if type is
1954 MAILIMAP_MSG_ATT_ENVELOPE
1955
1956 - internal_date is the date of message kept by the server if type is
1957 MAILIMAP_MSG_ATT_INTERNALDATE
1958
1959 - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822,
1960 should be allocated through a MMAPString
1961
1962 - rfc822_header is the message header if type is
1963 MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString
1964
1965 - rfc822_text is the message text part if type is
1966 MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString
1967
1968 - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE
1969
1970 - body is the MIME description of the message
1971
1972 - bodystructure is the MIME description of the message with additional
1973 information
1974
1975 - body_section is a MIME part content
1976
1977 - uid is a unique message identifier
1978*/
1979
1980struct mailimap_msg_att_static {
1981 int att_type;
1982 union {
1983 struct mailimap_envelope * att_env; /* can be NULL */
1984 struct mailimap_date_time * att_internal_date; /* can be NULL */
1985 struct {
1986 char * att_content; /* can be NULL */
1987 size_t att_length;
1988 } att_rfc822;
1989 struct {
1990 char * att_content; /* can be NULL */
1991 size_t att_length;
1992 } att_rfc822_header;
1993 struct {
1994 char * att_content; /* can be NULL */
1995 size_t att_length;
1996 } att_rfc822_text;
1997 uint32_t att_rfc822_size;
1998 struct mailimap_body * att_bodystructure; /* can be NULL */
1999 struct mailimap_body * att_body; /* can be NULL */
2000 struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */
2001 uint32_t att_uid;
2002 } att_data;
2003};
2004
2005struct mailimap_msg_att_static *
2006mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env,
2007 struct mailimap_date_time * att_internal_date,
2008 char * att_rfc822,
2009 char * att_rfc822_header,
2010 char * att_rfc822_text,
2011 size_t att_length,
2012 uint32_t att_rfc822_size,
2013 struct mailimap_body * att_bodystructure,
2014 struct mailimap_body * att_body,
2015 struct mailimap_msg_att_body_section * att_body_section,
2016 uint32_t att_uid);
2017
2018void
2019mailimap_msg_att_static_free(struct mailimap_msg_att_static * item);
2020
2021
2022
2023/* this is the type of a response element */
2024
2025enum {
2026 MAILIMAP_RESP_ERROR, /* on parse error */
2027 MAILIMAP_RESP_CONT_REQ, /* continuation request */
2028 MAILIMAP_RESP_RESP_DATA, /* response data */
2029};
2030
2031/*
2032 mailimap_cont_req_or_resp_data is a response element
2033
2034 - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ
2035 or MAILIMAP_RESP_RESP_DATA
2036
2037 - cont_req is a continuation request
2038
2039 - resp_data is a reponse data
2040*/
2041
2042struct mailimap_cont_req_or_resp_data {
2043 int rsp_type;
2044 union {
2045 struct mailimap_continue_req * rsp_cont_req; /* can be NULL */
2046 struct mailimap_response_data * rsp_resp_data; /* can be NULL */
2047 } rsp_data;
2048};
2049
2050struct mailimap_cont_req_or_resp_data *
2051mailimap_cont_req_or_resp_data_new(int rsp_type,
2052 struct mailimap_continue_req * rsp_cont_req,
2053 struct mailimap_response_data * rsp_resp_data);
2054
2055void
2056mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data *
2057 cont_req_or_resp_data);
2058
2059
2060/*
2061 mailimap_response is a list of response elements
2062
2063 - cont_req_or_resp_data_list is a list of response elements
2064
2065 - resp_done is an ending response element
2066*/
2067
2068struct mailimap_response {
2069 clist * rsp_cont_req_or_resp_data_list;
2070 /* list of (struct mailiap_cont_req_or_resp_data *) */
2071 /* can be NULL */
2072 struct mailimap_response_done * rsp_resp_done; /* != NULL */
2073};
2074
2075struct mailimap_response *
2076mailimap_response_new(clist * rsp_cont_req_or_resp_data_list,
2077 struct mailimap_response_done * rsp_resp_done);
2078
2079void
2080mailimap_response_free(struct mailimap_response * resp);
2081
2082
2083
2084/* this is the type of an untagged response */
2085
2086enum {
2087 MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */
2088 MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */
2089 MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about
2090 to close the connection) */
2091 MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */
2092 MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */
2093 MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */
2094};
2095
2096/*
2097 mailimap_reponse_data is an untagged response
2098
2099 - type is the type of the untagged response, it can be
2100 MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE,
2101 MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA
2102 or MAILIMAP_RESP_DATA_CAPABILITY_DATA
2103
2104 - cond_state is a condition state response
2105
2106 - bye is a BYE response (server is about to close the connection)
2107
2108 - mailbox_data is a response related to a mailbox
2109
2110 - message_data is a response related to a message
2111
2112 - capability is information about capabilities
2113*/
2114
2115struct mailimap_response_data {
2116 int rsp_type;
2117 union {
2118 struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */
2119 struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */
2120 struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */
2121 struct mailimap_message_data * rsp_message_data; /* can be NULL */
2122 struct mailimap_capability_data * rsp_capability_data; /* can be NULL */
2123 } rsp_data;
2124};
2125
2126struct mailimap_response_data *
2127mailimap_response_data_new(int rsp_type,
2128 struct mailimap_resp_cond_state * rsp_cond_state,
2129 struct mailimap_resp_cond_bye * rsp_bye,
2130 struct mailimap_mailbox_data * rsp_mailbox_data,
2131 struct mailimap_message_data * rsp_message_data,
2132 struct mailimap_capability_data * rsp_capability_data);
2133
2134void
2135mailimap_response_data_free(struct mailimap_response_data * resp_data);
2136
2137
2138
2139/* this is the type of an ending response */
2140
2141enum {
2142 MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */
2143 MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */
2144 MAILIMAP_RESP_DONE_TYPE_FATAL, /* fatal error response */
2145};
2146
2147/*
2148 mailimap_response_done is an ending response
2149
2150 - type is the type of the ending response
2151
2152 - tagged is a tagged response
2153
2154 - fatal is a fatal error response
2155*/
2156
2157struct mailimap_response_done {
2158 int rsp_type;
2159 union {
2160 struct mailimap_response_tagged * rsp_tagged; /* can be NULL */
2161 struct mailimap_response_fatal * rsp_fatal; /* can be NULL */
2162 } rsp_data;
2163};
2164
2165struct mailimap_response_done *
2166mailimap_response_done_new(int rsp_type,
2167 struct mailimap_response_tagged * rsp_tagged,
2168 struct mailimap_response_fatal * rsp_fatal);
2169
2170void mailimap_response_done_free(struct mailimap_response_done *
2171 resp_done);
2172
2173
2174/*
2175 mailimap_response_fatal is a fatal error response
2176
2177 - bye is a BYE response text
2178*/
2179
2180struct mailimap_response_fatal {
2181 struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */
2182};
2183
2184struct mailimap_response_fatal *
2185mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye);
2186
2187void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal);
2188
2189
2190
2191/*
2192 mailimap_response_tagged is a tagged response
2193
2194 - tag is the sent tag, should be allocated with malloc()
2195
2196 - cond_state is a condition state response
2197*/
2198
2199struct mailimap_response_tagged {
2200 char * rsp_tag; /* != NULL */
2201 struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */
2202};
2203
2204struct mailimap_response_tagged *
2205mailimap_response_tagged_new(char * rsp_tag,
2206 struct mailimap_resp_cond_state * rsp_cond_state);
2207
2208void
2209mailimap_response_tagged_free(struct mailimap_response_tagged * tagged);
2210
2211
2212/* this is the type of an authentication condition response */
2213
2214enum {
2215 MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */
2216 MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */
2217 MAILIMAP_RESP_COND_AUTH_PREAUTH, /* authentication is not needed */
2218};
2219
2220/*
2221 mailimap_resp_cond_auth is an authentication condition response
2222
2223 - type is the type of the authentication condition response,
2224 the value can be MAILIMAP_RESP_COND_AUTH_OK or
2225 MAILIMAP_RESP_COND_AUTH_PREAUTH
2226
2227 - text is a text response
2228*/
2229
2230struct mailimap_resp_cond_auth {
2231 int rsp_type;
2232 struct mailimap_resp_text * rsp_text; /* != NULL */
2233};
2234
2235struct mailimap_resp_cond_auth *
2236mailimap_resp_cond_auth_new(int rsp_type,
2237 struct mailimap_resp_text * rsp_text);
2238
2239void
2240mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth);
2241
2242
2243
2244/*
2245 mailimap_resp_cond_bye is a BYE response
2246
2247 - text is a text response
2248*/
2249
2250struct mailimap_resp_cond_bye {
2251 struct mailimap_resp_text * rsp_text; /* != NULL */
2252};
2253
2254struct mailimap_resp_cond_bye *
2255mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text);
2256
2257void
2258mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye);
2259
2260
2261
2262/* this is the type of a condition state response */
2263
2264enum {
2265 MAILIMAP_RESP_COND_STATE_OK,
2266 MAILIMAP_RESP_COND_STATE_NO,
2267 MAILIMAP_RESP_COND_STATE_BAD
2268};
2269
2270/*
2271 mailimap_resp_cond_state is a condition state reponse
2272
2273 - type is the type of the condition state response
2274
2275 - text is a text response
2276*/
2277
2278struct mailimap_resp_cond_state {
2279 int rsp_type;
2280 struct mailimap_resp_text * rsp_text; /* can be NULL */
2281};
2282
2283struct mailimap_resp_cond_state *
2284mailimap_resp_cond_state_new(int rsp_type,
2285 struct mailimap_resp_text * rsp_text);
2286
2287void
2288mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state);
2289
2290
2291
2292/*
2293 mailimap_resp_text is a text response
2294
2295 - resp_code is a response code
2296
2297 - text is a human readable text, should be allocated with malloc()
2298*/
2299
2300struct mailimap_resp_text {
2301 struct mailimap_resp_text_code * rsp_code; /* can be NULL */
2302 char * rsp_text; /* can be NULL */
2303};
2304
2305struct mailimap_resp_text *
2306mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code,
2307 char * rsp_text);
2308
2309void mailimap_resp_text_free(struct mailimap_resp_text * resp_text);
2310
2311
2312
2313/* this is the type of the response code */
2314
2315enum {
2316 MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */
2317 MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */
2318 MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */
2319 MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */
2320 MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */
2321 MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */
2322 MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */
2323 MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */
2324 MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */
2325 MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */
2326 MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */
2327 MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */
2328};
2329
2330/*
2331 mailimap_resp_text_code is a response code
2332
2333 - type is the type of the response code, the value can be
2334 MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET,
2335 MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE,
2336 MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY,
2337 MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE,
2338 MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY,
2339 MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER
2340
2341 - badcharset is a list of charsets if type
2342 is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be
2343 allocated with malloc()
2344
2345 - cap_data is a list of capabilities
2346
2347 - perm_flags is a list of flags, this is the flags that can be changed
2348 permanently on the messages of the mailbox.
2349
2350 - uidnext is the next unique identifier of a message
2351
2352 - uidvalidity is the unique identifier validity value
2353
2354 - first_unseen is the number of the first message without the \Seen flag
2355
2356 - atom is a keyword for an extension response code, should be allocated
2357 with malloc()
2358
2359 - atom_value is the data related with the extension response code,
2360 should be allocated with malloc()
2361*/
2362
2363struct mailimap_resp_text_code {
2364 int rc_type;
2365 union {
2366 clist * rc_badcharset; /* list of astring (char *) */
2367 /* can be NULL */
2368 struct mailimap_capability_data * rc_cap_data; /* != NULL */
2369 clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */
2370 /* can be NULL */
2371 uint32_t rc_uidnext;
2372 uint32_t rc_uidvalidity;
2373 uint32_t rc_first_unseen;
2374 struct {
2375 char * atom_name; /* can be NULL */
2376 char * atom_value; /* can be NULL */
2377 } rc_atom;
2378 } rc_data;
2379};
2380
2381struct mailimap_resp_text_code *
2382mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset,
2383 struct mailimap_capability_data * rc_cap_data,
2384 clist * rc_perm_flags,
2385 uint32_t rc_uidnext, uint32_t rc_uidvalidity,
2386 uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value);
2387
2388void
2389mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code);
2390
2391
2392/*
2393 mailimap_section is a MIME part section identifier
2394
2395 section_spec is the MIME section identifier
2396*/
2397
2398struct mailimap_section {
2399 struct mailimap_section_spec * sec_spec; /* can be NULL */
2400};
2401
2402struct mailimap_section *
2403mailimap_section_new(struct mailimap_section_spec * sec_spec);
2404
2405void mailimap_section_free(struct mailimap_section * section);
2406
2407
2408/* this is the type of the message/rfc822 part description */
2409
2410enum {
2411 MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the
2412 message */
2413 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the
2414 message */
2415 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the
2416 message except the given */
2417 MAILIMAP_SECTION_MSGTEXT_TEXT, /* text part */
2418};
2419
2420/*
2421 mailimap_section_msgtext is a message/rfc822 part description
2422
2423 - type is the type of the content part and the value can be
2424 MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS,
2425 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT
2426 or MAILIMAP_SECTION_MSGTEXT_TEXT
2427
2428 - header_list is the list of headers when type is
2429 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or
2430 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT
2431*/
2432
2433struct mailimap_section_msgtext {
2434 int sec_type;
2435 struct mailimap_header_list * sec_header_list; /* can be NULL */
2436};
2437
2438struct mailimap_section_msgtext *
2439mailimap_section_msgtext_new(int sec_type,
2440 struct mailimap_header_list * sec_header_list);
2441
2442void
2443mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext);
2444
2445
2446
2447/*
2448 mailimap_section_part is the MIME part location in a message
2449
2450 - section_id is a list of number index of the sub-part in the mail structure,
2451 each element should be allocated with malloc()
2452
2453*/
2454
2455struct mailimap_section_part {
2456 clist * sec_id; /* list of nz-number (uint32_t *) */
2457 /* != NULL */
2458};
2459
2460struct mailimap_section_part *
2461mailimap_section_part_new(clist * sec_id);
2462
2463void
2464mailimap_section_part_free(struct mailimap_section_part * section_part);
2465
2466
2467
2468/* this is the type of section specification */
2469
2470enum {
2471 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root
2472 MIME message/rfc822 part */
2473 MAILIMAP_SECTION_SPEC_SECTION_PART, /* location of the MIME part
2474 in the message */
2475};
2476
2477/*
2478 mailimap_section_spec is a section specification
2479
2480 - type is the type of the section specification, the value can be
2481 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or
2482 MAILIMAP_SECTION_SPEC_SECTION_PART
2483
2484 - section_msgtext is a message/rfc822 part description if type is
2485 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT
2486
2487 - section_part is a body part location in the message if type is
2488 MAILIMAP_SECTION_SPEC_SECTION_PART
2489
2490 - section_text is a body part location for a given MIME part,
2491 this can be NULL if the body of the part is requested (and not
2492 the MIME header).
2493*/
2494
2495struct mailimap_section_spec {
2496 int sec_type;
2497 union {
2498 struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */
2499 struct mailimap_section_part * sec_part; /* can be NULL */
2500 } sec_data;
2501 struct mailimap_section_text * sec_text; /* can be NULL */
2502};
2503
2504struct mailimap_section_spec *
2505mailimap_section_spec_new(int sec_type,
2506 struct mailimap_section_msgtext * sec_msgtext,
2507 struct mailimap_section_part * sec_part,
2508 struct mailimap_section_text * sec_text);
2509
2510void
2511mailimap_section_spec_free(struct mailimap_section_spec * section_spec);
2512
2513
2514
2515/* this is the type of body part location for a given MIME part */
2516
2517enum {
2518 MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/
2519 MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is
2520 message/rfc822, headers or text
2521 can be requested */
2522 MAILIMAP_SECTION_TEXT_MIME, /* for all MIME types,
2523 MIME headers can be requested */
2524};
2525
2526/*
2527 mailimap_section_text is the body part location for a given MIME part
2528
2529 - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or
2530 MAILIMAP_SECTION_TEXT_MIME
2531
2532 - section_msgtext is the part of the MIME part when MIME type is
2533 message/rfc822 than can be requested, when type is
2534 MAILIMAP_TEXT_SECTION_MSGTEXT
2535*/
2536
2537struct mailimap_section_text {
2538 int sec_type;
2539 struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */
2540};
2541
2542struct mailimap_section_text *
2543mailimap_section_text_new(int sec_type,
2544 struct mailimap_section_msgtext * sec_msgtext);
2545
2546void
2547mailimap_section_text_free(struct mailimap_section_text * section_text);
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558/* ************************************************************************* */
2559/* the following part concerns only the IMAP command that are sent */
2560
2561
2562/*
2563 mailimap_set_item is a message set
2564
2565 - first is the first message of the set
2566 - last is the last message of the set
2567
2568 this can be message numbers of message unique identifiers
2569*/
2570
2571struct mailimap_set_item {
2572 uint32_t set_first;
2573 uint32_t set_last;
2574};
2575
2576struct mailimap_set_item *
2577mailimap_set_item_new(uint32_t set_first, uint32_t set_last);
2578
2579void mailimap_set_item_free(struct mailimap_set_item * set_item);
2580
2581
2582
2583/*
2584 set is a list of message sets
2585
2586 - list is a list of message sets
2587*/
2588
2589struct mailimap_set {
2590 clist * set_list; /* list of (struct mailimap_set_item *) */
2591};
2592
2593struct mailimap_set * mailimap_set_new(clist * list);
2594
2595void mailimap_set_free(struct mailimap_set * set);
2596
2597
2598/*
2599 mailimap_date is a date
2600
2601 - day is the day in the month (1 to 31)
2602
2603 - month (1 to 12)
2604
2605 - year (4 digits)
2606*/
2607
2608struct mailimap_date {
2609 int dt_day;
2610 int dt_month;
2611 int dt_year;
2612};
2613
2614struct mailimap_date *
2615mailimap_date_new(int dt_day, int dt_month, int dt_year);
2616
2617void mailimap_date_free(struct mailimap_date * date);
2618
2619
2620
2621
2622/* this is the type of fetch attribute for a given message */
2623
2624enum {
2625 MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by
2626 the IMAP server */
2627 MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */
2628 MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message
2629 kept by the server */
2630 MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */
2631 MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */
2632 MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */
2633 MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */
2634 MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */
2635 MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with
2636 additional information */
2637 MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */
2638 MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */
2639 MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without
2640 marking the message as read */
2641};
2642
2643
2644/*
2645 mailimap_fetch_att is the description of the fetch attribute
2646
2647 - type is the type of fetch attribute, the value can be
2648 MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS,
2649 MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822,
2650 MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE,
2651 MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY,
2652 MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID,
2653 MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION
2654
2655 - section is the location of the part to fetch if type is
2656 MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION
2657
2658 - offset is the first byte to fetch in the given part
2659
2660 - size is the maximum size of the part to fetch
2661*/
2662
2663struct mailimap_fetch_att {
2664 int att_type;
2665 struct mailimap_section * att_section;
2666 uint32_t att_offset;
2667 uint32_t att_size;
2668};
2669
2670struct mailimap_fetch_att *
2671mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section,
2672 uint32_t att_offset, uint32_t att_size);
2673
2674
2675void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att);
2676
2677
2678/* this is the type of a FETCH operation */
2679
2680enum {
2681 MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE
2682 RFC822.SIZE ENVELOPE) */
2683 MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE
2684 RFC822.SIZE ENVELOPE BODY) */
2685 MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE
2686 RFC822.SIZE) */
2687 MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch
2688 attribute */
2689 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, /* when there is a list of fetch
2690 attributes */
2691};
2692
2693/*
2694 mailimap_fetch_type is the description of the FETCH operation
2695
2696 - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL,
2697 MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or
2698 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST
2699
2700 - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT
2701
2702 - fetch_att_list is a list of fetch attributes if type is
2703 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST
2704*/
2705
2706struct mailimap_fetch_type {
2707 int ft_type;
2708 union {
2709 struct mailimap_fetch_att * ft_fetch_att;
2710 clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */
2711 } ft_data;
2712};
2713
2714struct mailimap_fetch_type *
2715mailimap_fetch_type_new(int ft_type,
2716 struct mailimap_fetch_att * ft_fetch_att,
2717 clist * ft_fetch_att_list);
2718
2719
2720void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type);
2721
2722
2723
2724/*
2725 mailimap_store_att_flags is the description of the STORE operation
2726 (change flags of a message)
2727
2728 - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag)
2729
2730 - silent has a value of 1 if the flags are changed with no server
2731 response
2732
2733 - flag_list is the list of flags to change
2734*/
2735
2736struct mailimap_store_att_flags {
2737 int fl_sign;
2738 int fl_silent;
2739 struct mailimap_flag_list * fl_flag_list;
2740};
2741
2742struct mailimap_store_att_flags *
2743mailimap_store_att_flags_new(int fl_sign, int fl_silent,
2744 struct mailimap_flag_list * fl_flag_list);
2745
2746void mailimap_store_att_flags_free(struct mailimap_store_att_flags *
2747 store_att_flags);
2748
2749
2750
2751/* this is the condition of the SEARCH operation */
2752
2753enum {
2754 MAILIMAP_SEARCH_KEY_ALL, /* all messages */
2755 MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */
2756 MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the
2757 given string */
2758 MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier
2759 than the specified date */
2760 MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string
2761 (in header and text parts) */
2762 MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the
2763 given string */
2764 MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */
2765 MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */
2766 MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the
2767 given string */
2768 MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */
2769 MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not
2770 the \Seen flag */
2771 MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the
2772 \Recent flag set */
2773 MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the
2774 specified date */
2775 MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */
2776 MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */
2777 MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later
2778 than specified date */
2779 MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the
2780 given string */
2781 MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the
2782 given string */
2783 MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the
2784 given string */
2785 MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */
2786 MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */
2787 MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */
2788 MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */
2789 MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */
2790 MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */
2791 MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field
2792 contains the given string */
2793 MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then
2794 the given size */
2795 MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */
2796 MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */
2797 MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header
2798 is earlier than the specified date */
2799 MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header
2800 is the specified date */
2801 MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header
2802 is later than specified date */
2803 MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than
2804 the given size */
2805 MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are
2806 in the given range */
2807 MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */
2808 MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique
2809 identifiers in case of UID SEARCH) are
2810 in the given range */
2811 MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the
2812 conditions is AND */
2813};
2814
2815/*
2816 mailimap_search_key is the condition on the messages to return
2817
2818 - type is the type of the condition
2819
2820 - bcc is the text to search in the Bcc field when type is
2821 MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc()
2822
2823 - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE
2824
2825 - body is the text to search in the message when type is
2826 MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc()
2827
2828 - cc is the text to search in the Cc field when type is
2829 MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc()
2830
2831 - from is the text to search in the From field when type is
2832 MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc()
2833
2834 - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD,
2835 should be allocated with malloc()
2836
2837 - on is a date when type is MAILIMAP_SEARCH_KEY_ON
2838
2839 - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE
2840
2841 - subject is the text to search in the Subject field when type is
2842 MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc()
2843
2844 - text is the text to search in the text part of the message when
2845 type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc()
2846
2847 - to is the text to search in the To field when type is
2848 MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc()
2849
2850 - unkeyword is the keyword flag name when type is
2851 MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc()
2852
2853 - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER,
2854 should be allocated with malloc()
2855
2856 - header_value is the text to search in the given header when type is
2857 MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc()
2858
2859 - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER
2860
2861 - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT
2862
2863 - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR
2864
2865 - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR
2866
2867 - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE
2868
2869 - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON
2870
2871 - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE
2872
2873 - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER
2874
2875 - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID
2876
2877 - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET
2878
2879 - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE
2880*/
2881
2882struct mailimap_search_key {
2883 int sk_type;
2884 union {
2885 char * sk_bcc;
2886 struct mailimap_date * sk_before;
2887 char * sk_body;
2888 char * sk_cc;
2889 char * sk_from;
2890 char * sk_keyword;
2891 struct mailimap_date * sk_on;
2892 struct mailimap_date * sk_since;
2893 char * sk_subject;
2894 char * sk_text;
2895 char * sk_to;
2896 char * sk_unkeyword;
2897 struct {
2898 char * sk_header_name;
2899 char * sk_header_value;
2900 } sk_header;
2901 uint32_t sk_larger;
2902 struct mailimap_search_key * sk_not;
2903 struct {
2904 struct mailimap_search_key * sk_or1;
2905 struct mailimap_search_key * sk_or2;
2906 } sk_or;
2907 struct mailimap_date * sk_sentbefore;
2908 struct mailimap_date * sk_senton;
2909 struct mailimap_date * sk_sentsince;
2910 uint32_t sk_smaller;
2911 struct mailimap_set * sk_uid;
2912 struct mailimap_set * sk_set;
2913 clist * sk_multiple; /* list of (struct mailimap_search_key *) */
2914 } sk_data;
2915};
2916
2917struct mailimap_search_key *
2918mailimap_search_key_new(int sk_type,
2919 char * sk_bcc, struct mailimap_date * sk_before, char * sk_body,
2920 char * sk_cc, char * sk_from, char * sk_keyword,
2921 struct mailimap_date * sk_on, struct mailimap_date * sk_since,
2922 char * sk_subject, char * sk_text, char * sk_to,
2923 char * sk_unkeyword, char * sk_header_name,
2924 char * sk_header_value, uint32_t sk_larger,
2925 struct mailimap_search_key * sk_not,
2926 struct mailimap_search_key * sk_or1,
2927 struct mailimap_search_key * sk_or2,
2928 struct mailimap_date * sk_sentbefore,
2929 struct mailimap_date * sk_senton,
2930 struct mailimap_date * sk_sentsince,
2931 uint32_t sk_smaller, struct mailimap_set * sk_uid,
2932 struct mailimap_set * sk_set, clist * sk_multiple);
2933
2934
2935void mailimap_search_key_free(struct mailimap_search_key * key);
2936
2937
2938/*
2939 mailimap_status_att_list is a list of mailbox STATUS request type
2940
2941 - list is a list of mailbox STATUS request type
2942 (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES,
2943 MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT,
2944 MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN),
2945 each element should be allocated with malloc()
2946*/
2947
2948struct mailimap_status_att_list {
2949 clist * att_list; /* list of (uint32_t *) */
2950};
2951
2952struct mailimap_status_att_list *
2953mailimap_status_att_list_new(clist * att_list);
2954
2955void mailimap_status_att_list_free(struct mailimap_status_att_list *
2956 status_att_list);
2957
2958
2959
2960
2961/* internal use functions */
2962
2963
2964uint32_t * mailimap_number_alloc_new(uint32_t number);
2965
2966void mailimap_number_alloc_free(uint32_t * pnumber);
2967
2968
2969void mailimap_addr_host_free(char * addr_host);
2970
2971void mailimap_addr_mailbox_free(char * addr_mailbox);
2972
2973void mailimap_addr_adl_free(char * addr_adl);
2974
2975void mailimap_addr_name_free(char * addr_name);
2976
2977void mailimap_astring_free(char * astring);
2978
2979void mailimap_atom_free(char * atom);
2980
2981void mailimap_auth_type_free(char * auth_type);
2982
2983void mailimap_base64_free(char * base64);
2984
2985void mailimap_body_fld_desc_free(char * body_fld_desc);
2986
2987void mailimap_body_fld_id_free(char * body_fld_id);
2988
2989void mailimap_body_fld_md5_free(char * body_fld_md5);
2990
2991void mailimap_env_date_free(char * date);
2992
2993void mailimap_env_in_reply_to_free(char * in_reply_to);
2994
2995void mailimap_env_message_id_free(char * message_id);
2996
2997void mailimap_env_subject_free(char * subject);
2998
2999void mailimap_flag_extension_free(char * flag_extension);
3000
3001void mailimap_flag_keyword_free(char * flag_keyword);
3002
3003void
3004mailimap_header_fld_name_free(char * header_fld_name);
3005
3006void mailimap_literal_free(char * literal);
3007
3008void mailimap_mailbox_free(char * mailbox);
3009
3010void
3011mailimap_mailbox_data_search_free(clist * data_search);
3012
3013void mailimap_media_subtype_free(char * media_subtype);
3014
3015void mailimap_media_text_free(char * media_text);
3016
3017void mailimap_msg_att_envelope_free(struct mailimap_envelope * env);
3018
3019void
3020mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time);
3021
3022void
3023mailimap_msg_att_rfc822_free(char * str);
3024
3025void
3026mailimap_msg_att_rfc822_header_free(char * str);
3027
3028void
3029mailimap_msg_att_rfc822_text_free(char * str);
3030
3031void
3032mailimap_msg_att_body_free(struct mailimap_body * body);
3033
3034void
3035mailimap_msg_att_bodystructure_free(struct mailimap_body * body);
3036
3037void mailimap_nstring_free(char * str);
3038
3039void
3040mailimap_string_free(char * str);
3041
3042void mailimap_tag_free(char * tag);
3043
3044void mailimap_text_free(char * text);
3045
3046
3047
3048
3049
3050/* IMAP connection */
3051
3052/* this is the state of the IMAP connection */
3053
3054enum {
3055 MAILIMAP_STATE_DISCONNECTED,
3056 MAILIMAP_STATE_NON_AUTHENTICATED,
3057 MAILIMAP_STATE_AUTHENTICATED,
3058 MAILIMAP_STATE_SELECTED,
3059 MAILIMAP_STATE_LOGOUT
3060};
3061
3062/*
3063 mailimap is an IMAP connection
3064
3065 - response is a human readable message returned with a reponse,
3066 must be accessed read-only
3067
3068 - stream is the connection with the IMAP server
3069
3070 - stream_buffer is the buffer where the data to parse are stored
3071
3072 - state is the state of IMAP connection
3073
3074 - tag is the current tag being used in IMAP connection
3075
3076 - response_buffer is the buffer for response messages
3077
3078 - connection_info is the information returned in response
3079 for the last command about the connection
3080
3081 - selection_info is the information returned in response
3082 for the last command about the current selected mailbox
3083
3084 - response_info is the other information returned in response
3085 for the last command
3086*/
3087
3088struct mailimap {
3089 char * imap_response;
3090
3091 /* internals */
3092 mailstream * imap_stream;
3093
3094 size_t imap_progr_rate;
3095 progress_function * imap_progr_fun;
3096
3097 MMAPString * imap_stream_buffer;
3098 MMAPString * imap_response_buffer;
3099
3100 int imap_state;
3101 int imap_tag;
3102
3103 struct mailimap_connection_info * imap_connection_info;
3104 struct mailimap_selection_info * imap_selection_info;
3105 struct mailimap_response_info * imap_response_info;
3106};
3107
3108typedef struct mailimap mailimap;
3109
3110
3111/*
3112 mailimap_connection_info is the information about the connection
3113
3114 - capability is the list of capability of the IMAP server
3115*/
3116
3117struct mailimap_connection_info {
3118 struct mailimap_capability_data * imap_capability;
3119};
3120
3121struct mailimap_connection_info *
3122mailimap_connection_info_new(void);
3123
3124void
3125mailimap_connection_info_free(struct mailimap_connection_info * conn_info);
3126
3127
3128/* this is the type of mailbox access */
3129
3130enum {
3131 MAILIMAP_MAILBOX_READONLY,
3132 MAILIMAP_MAILBOX_READWRITE
3133};
3134
3135/*
3136 mailimap_selection_info is information about the current selected mailbox
3137
3138 - perm_flags is a list of flags that can be changed permanently on the
3139 messages of the mailbox
3140
3141 - perm is the access on the mailbox, value can be
3142 MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE
3143
3144 - uidnext is the next unique identifier
3145
3146 - uidvalidity is the unique identifiers validity
3147
3148 - first_unseen is the number of the first unseen message
3149
3150 - flags is a list of flags that can be used on the messages of
3151 the mailbox
3152
3153 - exists is the number of messages in the mailbox
3154
3155 - recent is the number of recent messages in the mailbox
3156
3157 - unseen is the number of unseen messages in the mailbox
3158*/
3159
3160struct mailimap_selection_info {
3161 clist * sel_perm_flags; /* list of (struct flag_perm *) */
3162 int sel_perm;
3163 uint32_t sel_uidnext;
3164 uint32_t sel_uidvalidity;
3165 uint32_t sel_first_unseen;
3166 struct mailimap_flag_list * sel_flags;
3167 uint32_t sel_exists;
3168 uint32_t sel_recent;
3169 uint32_t sel_unseen;
3170};
3171
3172struct mailimap_selection_info *
3173mailimap_selection_info_new(void);
3174
3175void
3176mailimap_selection_info_free(struct mailimap_selection_info * sel_info);
3177
3178
3179/*
3180 mailimap_response_info is the other information returned in the
3181 response for a command
3182
3183 - alert is the human readable text returned with ALERT response
3184
3185 - parse is the human readable text returned with PARSE response
3186
3187 - badcharset is a list of charset returned with a BADCHARSET response
3188
3189 - trycreate is set to 1 if a trycreate response was returned
3190
3191 - mailbox_list is a list of mailboxes
3192
3193 - mailbox_lsub is a list of subscribed mailboxes
3194
3195 - search_result is a list of message numbers or unique identifiers
3196
3197 - status is a STATUS response
3198
3199 - expunged is a list of message numbers
3200
3201 - fetch_list is a list of fetch response
3202*/
3203
3204struct mailimap_response_info {
3205 char * rsp_alert;
3206 char * rsp_parse;
3207 clist * rsp_badcharset; /* list of (char *) */
3208 int rsp_trycreate;
3209 clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */
3210 clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */
3211 clist * rsp_search_result; /* list of (uint32_t *) */
3212 struct mailimap_mailbox_data_status * rsp_status;
3213 clist * rsp_expunged; /* list of (uint32_t 32 *) */
3214 clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */
3215};
3216
3217struct mailimap_response_info *
3218mailimap_response_info_new(void);
3219
3220void
3221mailimap_response_info_free(struct mailimap_response_info * resp_info);
3222
3223
3224/* these are the possible returned error codes */
3225
3226enum {
3227 MAILIMAP_NO_ERROR = 0,
3228 MAILIMAP_NO_ERROR_AUTHENTICATED = 1,
3229 MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2,
3230 MAILIMAP_ERROR_BAD_STATE,
3231 MAILIMAP_ERROR_STREAM,
3232 MAILIMAP_ERROR_PARSE,
3233 MAILIMAP_ERROR_CONNECTION_REFUSED,
3234 MAILIMAP_ERROR_MEMORY,
3235 MAILIMAP_ERROR_FATAL,
3236 MAILIMAP_ERROR_PROTOCOL,
3237 MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION,
3238 MAILIMAP_ERROR_APPEND,
3239 MAILIMAP_ERROR_NOOP,
3240 MAILIMAP_ERROR_LOGOUT,
3241 MAILIMAP_ERROR_CAPABILITY,
3242 MAILIMAP_ERROR_CHECK,
3243 MAILIMAP_ERROR_CLOSE,
3244 MAILIMAP_ERROR_EXPUNGE,
3245 MAILIMAP_ERROR_COPY,
3246 MAILIMAP_ERROR_UID_COPY,
3247 MAILIMAP_ERROR_CREATE,
3248 MAILIMAP_ERROR_DELETE,
3249 MAILIMAP_ERROR_EXAMINE,
3250 MAILIMAP_ERROR_FETCH,
3251 MAILIMAP_ERROR_UID_FETCH,
3252 MAILIMAP_ERROR_LIST,
3253 MAILIMAP_ERROR_LOGIN,
3254 MAILIMAP_ERROR_LSUB,
3255 MAILIMAP_ERROR_RENAME,
3256 MAILIMAP_ERROR_SEARCH,
3257 MAILIMAP_ERROR_UID_SEARCH,
3258 MAILIMAP_ERROR_SELECT,
3259 MAILIMAP_ERROR_STATUS,
3260 MAILIMAP_ERROR_STORE,
3261 MAILIMAP_ERROR_UID_STORE,
3262 MAILIMAP_ERROR_SUBSCRIBE,
3263 MAILIMAP_ERROR_UNSUBSCRIBE,
3264 MAILIMAP_ERROR_STARTTLS,
3265 MAILIMAP_ERROR_INVAL,
3266};
3267
3268
3269#ifdef __cplusplus
3270}
3271#endif
3272
3273#endif
3274
diff --git a/libetpan/include/libetpan/mailimap_types_helper.h b/libetpan/include/libetpan/mailimap_types_helper.h
new file mode 100644
index 0000000..10905d4
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimap_types_helper.h
@@ -0,0 +1,758 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_TYPES_HELPER_H
37
38#define MAILIMAP_TYPES_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45
46/*
47 IMPORTANT NOTE:
48
49 All allocation functions will take as argument allocated data
50 and will store these data in the structure they will allocate.
51 Data should be persistant during all the use of the structure
52 and will be freed by the free function of the structure
53
54 allocation functions will return NULL on failure
55*/
56
57/*
58 this function creates a new set item with a single message
59 given by index
60*/
61
62struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index);
63
64/*
65 this function creates a new set with one set item
66 */
67
68struct mailimap_set *
69mailimap_set_new_single_item(struct mailimap_set_item * item);
70
71/*
72 this function creates a set with a single interval
73*/
74
75struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last);
76
77/*
78 this function creates a set with a single message
79*/
80
81struct mailimap_set * mailimap_set_new_single(uint32_t index);
82
83/*
84 this function creates an empty set of messages
85*/
86
87struct mailimap_set * mailimap_set_new_empty(void);
88
89/*
90 this function adds a set item to the set of messages
91
92 @return MAILIMAP_NO_ERROR will be returned on success,
93 other code will be returned otherwise
94*/
95
96int mailimap_set_add(struct mailimap_set * set,
97 struct mailimap_set_item * set_item);
98
99/*
100 this function adds an interval to the set
101
102 @return MAILIMAP_NO_ERROR will be returned on success,
103 other code will be returned otherwise
104*/
105
106int mailimap_set_add_interval(struct mailimap_set * set,
107 uint32_t first, uint32_t last);
108
109/*
110 this function adds a single message to the set
111
112 @return MAILIMAP_NO_ERROR will be returned on success,
113 other code will be returned otherwise
114*/
115
116int mailimap_set_add_single(struct mailimap_set * set,
117 uint32_t index);
118
119/*
120 this function creates a mailimap_section structure to request
121 the header of a message
122*/
123
124struct mailimap_section * mailimap_section_new_header(void);
125
126/*
127 this functions creates a mailimap_section structure to describe
128 a list of headers
129*/
130
131struct mailimap_section *
132mailimap_section_new_header_fields(struct mailimap_header_list * header_list);
133
134/*
135 this functions creates a mailimap_section structure to describe headers
136 other than those given
137*/
138
139struct mailimap_section *
140mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list);
141
142/*
143 this function creates a mailimap_section structure to describe the
144 text of a message
145 */
146
147struct mailimap_section * mailimap_section_new_text(void);
148
149/*
150 this function creates a mailimap_section structure to describe the
151 content of a MIME part
152*/
153
154struct mailimap_section *
155mailimap_section_new_part(struct mailimap_section_part * part);
156
157/*
158 this function creates a mailimap_section structure to describe the
159 MIME fields of a MIME part
160*/
161
162struct mailimap_section *
163mailimap_section_new_part_mime(struct mailimap_section_part * part);
164
165/*
166 this function creates a mailimap_section structure to describe the
167 headers of a MIME part if the MIME type is a message/rfc822
168*/
169
170struct mailimap_section *
171mailimap_section_new_part_header(struct mailimap_section_part * part);
172
173/*
174 this function creates a mailimap_section structure to describe
175 a list of headers of a MIME part if the MIME type is a message/rfc822
176*/
177
178struct mailimap_section *
179mailimap_section_new_part_header_fields(struct mailimap_section_part *
180 part,
181 struct mailimap_header_list *
182 header_list);
183
184/*
185 this function creates a mailimap_section structure to describe
186 headers of a MIME part other than those given if the MIME type
187 is a message/rfc822
188*/
189
190struct mailimap_section *
191mailimap_section_new_part_header_fields_not(struct mailimap_section_part
192 * part,
193 struct mailimap_header_list
194 * header_list);
195
196/*
197 this function creates a mailimap_section structure to describe
198 text part of message if the MIME type is a message/rfc822
199*/
200
201struct mailimap_section *
202mailimap_section_new_part_text(struct mailimap_section_part * part);
203
204
205/*
206 this function creates a mailimap_fetch_att structure to request
207 envelope of a message
208*/
209
210struct mailimap_fetch_att *
211mailimap_fetch_att_new_envelope(void);
212
213
214/*
215 this function creates a mailimap_fetch_att structure to request
216 flags of a message
217*/
218
219struct mailimap_fetch_att *
220mailimap_fetch_att_new_flags(void);
221
222/*
223 this function creates a mailimap_fetch_att structure to request
224 internal date of a message
225*/
226
227struct mailimap_fetch_att *
228mailimap_fetch_att_new_internaldate(void);
229
230
231/*
232 this function creates a mailimap_fetch_att structure to request
233 text part of a message
234*/
235
236struct mailimap_fetch_att *
237mailimap_fetch_att_new_rfc822(void);
238
239
240/*
241 this function creates a mailimap_fetch_att structure to request
242 header of a message
243*/
244
245struct mailimap_fetch_att *
246mailimap_fetch_att_new_rfc822_header(void);
247
248/*
249 this function creates a mailimap_fetch_att structure to request
250 size of a message
251*/
252
253struct mailimap_fetch_att *
254mailimap_fetch_att_new_rfc822_size(void);
255
256/*
257 this function creates a mailimap_fetch_att structure to request
258 envelope of a message
259*/
260
261struct mailimap_fetch_att *
262mailimap_fetch_att_new_rfc822_text(void);
263
264/*
265 this function creates a mailimap_fetch_att structure to request
266 the MIME structure of a message
267*/
268
269struct mailimap_fetch_att *
270mailimap_fetch_att_new_body(void);
271
272/*
273 this function creates a mailimap_fetch_att structure to request
274 the MIME structure of a message and additional MIME information
275*/
276
277struct mailimap_fetch_att *
278mailimap_fetch_att_new_bodystructure(void);
279
280/*
281 this function creates a mailimap_fetch_att structure to request
282 unique identifier of a message
283*/
284
285struct mailimap_fetch_att *
286mailimap_fetch_att_new_uid(void);
287
288/*
289 this function creates a mailimap_fetch_att structure to request
290 a given section of a message
291*/
292
293struct mailimap_fetch_att *
294mailimap_fetch_att_new_body_section(struct mailimap_section * section);
295
296/*
297 this function creates a mailimap_fetch_att structure to request
298 a given section of a message without marking it as read
299*/
300
301struct mailimap_fetch_att *
302mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section);
303
304/*
305 this function creates a mailimap_fetch_att structure to request
306 a part of a section of a message
307*/
308
309struct mailimap_fetch_att *
310mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section,
311 uint32_t offset, uint32_t size);
312
313/*
314 this function creates a mailimap_fetch_att structure to request
315 a part of a section of a message without marking it as read
316*/
317
318struct mailimap_fetch_att *
319mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section,
320 uint32_t offset, uint32_t size);
321
322/*
323 this function creates a mailimap_fetch_type structure to request
324 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message
325*/
326
327struct mailimap_fetch_type *
328mailimap_fetch_type_new_all(void);
329
330/*
331 this function creates a mailimap_fetch_type structure to request
332 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY)
333*/
334
335struct mailimap_fetch_type *
336mailimap_fetch_type_new_full(void);
337
338/*
339 this function creates a mailimap_fetch_type structure to request
340 (FLAGS INTERNALDATE RFC822.SIZE)
341*/
342
343struct mailimap_fetch_type *
344mailimap_fetch_type_new_fast(void);
345
346/*
347 this function creates a mailimap_fetch_type structure to request
348 the given fetch attribute
349*/
350
351struct mailimap_fetch_type *
352mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att);
353
354/*
355 this function creates a mailimap_fetch_type structure to request
356 the list of fetch attributes
357*/
358
359struct mailimap_fetch_type *
360mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list);
361
362/*
363 this function creates a mailimap_fetch_type structure
364*/
365
366struct mailimap_fetch_type *
367mailimap_fetch_type_new_fetch_att_list_empty(void);
368
369/*
370 this function adds a given fetch attribute to the mailimap_fetch
371 structure
372
373 @return MAILIMAP_NO_ERROR will be returned on success,
374 other code will be returned otherwise
375*/
376
377int
378mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type *
379 fetch_type,
380 struct mailimap_fetch_att *
381 fetch_att);
382
383/*
384 this function creates a store attribute to set the given flags
385*/
386
387struct mailimap_store_att_flags *
388mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags);
389
390/*
391 this function creates a store attribute to silently set the given flags
392*/
393
394struct mailimap_store_att_flags *
395mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list *
396 flags);
397
398/*
399 this function creates a store attribute to add the given flags
400*/
401
402struct mailimap_store_att_flags *
403mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags);
404
405/*
406 this function creates a store attribute to add silently the given flags
407*/
408
409struct mailimap_store_att_flags *
410mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list *
411 flags);
412
413/*
414 this function creates a store attribute to remove the given flags
415*/
416
417struct mailimap_store_att_flags *
418mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags);
419
420/*
421 this function creates a store attribute to remove silently the given flags
422*/
423
424struct mailimap_store_att_flags *
425mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list *
426 flags);
427
428
429/*
430 this function creates a condition structure to match all messages
431*/
432
433struct mailimap_search_key *
434mailimap_search_key_new_all(void);
435
436/*
437 this function creates a condition structure to match messages with Bcc field
438
439 @param bcc this is the content of Bcc to match, it should be allocated
440 with malloc()
441*/
442
443struct mailimap_search_key *
444mailimap_search_key_new_bcc(char * sk_bcc);
445
446/*
447 this function creates a condition structure to match messages with
448 internal date
449*/
450
451struct mailimap_search_key *
452mailimap_search_key_new_before(struct mailimap_date * sk_before);
453
454/*
455 this function creates a condition structure to match messages with
456 message content
457
458 @param body this is the content of the message to match, it should
459 be allocated with malloc()
460*/
461
462struct mailimap_search_key *
463mailimap_search_key_new_body(char * sk_body);
464
465/*
466 this function creates a condition structure to match messages with
467 Cc field
468
469
470 @param cc this is the content of Cc to match, it should be allocated
471 with malloc()
472*/
473
474struct mailimap_search_key *
475mailimap_search_key_new_cc(char * sk_cc);
476
477/*
478 this function creates a condition structure to match messages with
479 From field
480
481 @param from this is the content of From to match, it should be allocated
482 with malloc()
483*/
484
485struct mailimap_search_key *
486mailimap_search_key_new_from(char * sk_from);
487
488/*
489 this function creates a condition structure to match messages with
490 a flag given by keyword
491*/
492
493struct mailimap_search_key *
494mailimap_search_key_new_keyword(char * sk_keyword);
495
496/*
497 this function creates a condition structure to match messages with
498 internal date
499*/
500
501struct mailimap_search_key *
502mailimap_search_key_new_on(struct mailimap_date * sk_on);
503
504/*
505 this function creates a condition structure to match messages with
506 internal date
507*/
508
509struct mailimap_search_key *
510mailimap_search_key_new_since(struct mailimap_date * sk_since);
511
512/*
513 this function creates a condition structure to match messages with
514 Subject field
515
516 @param subject this is the content of Subject to match, it should
517 be allocated with malloc()
518*/
519
520struct mailimap_search_key *
521mailimap_search_key_new_subject(char * sk_subject);
522
523/*
524 this function creates a condition structure to match messages with
525 message text part
526
527 @param text this is the message text to match, it should
528 be allocated with malloc()
529*/
530
531struct mailimap_search_key *
532mailimap_search_key_new_text(char * sk_text);
533
534/*
535 this function creates a condition structure to match messages with
536 To field
537
538 @param to this is the content of To to match, it should be allocated
539 with malloc()
540*/
541
542struct mailimap_search_key *
543mailimap_search_key_new_to(char * sk_to);
544
545/*
546 this function creates a condition structure to match messages with
547 no a flag given by unkeyword
548*/
549
550struct mailimap_search_key *
551mailimap_search_key_new_unkeyword(char * sk_unkeyword);
552
553/*
554 this function creates a condition structure to match messages with
555 the given field
556
557 @param header_name this is the name of the field to match, it
558 should be allocated with malloc()
559
560 @param header_value this is the content, it should be allocated
561 with malloc()
562*/
563
564struct mailimap_search_key *
565mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value);
566
567
568/*
569 this function creates a condition structure to match messages with size
570*/
571
572struct mailimap_search_key *
573mailimap_search_key_new_larger(uint32_t sk_larger);
574
575/*
576 this function creates a condition structure to match messages that
577 do not match the given condition
578*/
579
580struct mailimap_search_key *
581mailimap_search_key_new_not(struct mailimap_search_key * sk_not);
582
583/*
584 this function creates a condition structure to match messages that
585 match one of the given conditions
586*/
587
588struct mailimap_search_key *
589mailimap_search_key_new_or(struct mailimap_search_key * sk_or1,
590 struct mailimap_search_key * sk_or2);
591
592/*
593 this function creates a condition structure to match messages
594 with Date field
595*/
596
597struct mailimap_search_key *
598mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore);
599
600/*
601 this function creates a condition structure to match messages
602 with Date field
603*/
604
605struct mailimap_search_key *
606mailimap_search_key_new_senton(struct mailimap_date * sk_senton);
607
608/*
609 this function creates a condition structure to match messages
610 with Date field
611*/
612
613struct mailimap_search_key *
614mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince);
615
616/*
617 this function creates a condition structure to match messages with size
618*/
619
620struct mailimap_search_key *
621mailimap_search_key_new_smaller(uint32_t sk_smaller);
622
623/*
624 this function creates a condition structure to match messages with unique
625 identifier
626*/
627
628struct mailimap_search_key *
629mailimap_search_key_new_uid(struct mailimap_set * sk_uid);
630
631/*
632 this function creates a condition structure to match messages with number
633 or unique identifier (depending whether SEARCH or UID SEARCH is used)
634*/
635
636struct mailimap_search_key *
637mailimap_search_key_new_set(struct mailimap_set * sk_set);
638
639/*
640 this function creates a condition structure to match messages that match
641 all the conditions given in the list
642*/
643
644struct mailimap_search_key *
645mailimap_search_key_new_multiple(clist * sk_multiple);
646
647
648/*
649 same as previous but the list is empty
650*/
651
652struct mailimap_search_key *
653mailimap_search_key_new_multiple_empty(void);
654
655/*
656 this function adds a condition to the condition list
657
658 @return MAILIMAP_NO_ERROR will be returned on success,
659 other code will be returned otherwise
660*/
661
662int
663mailimap_search_key_multiple_add(struct mailimap_search_key * keys,
664 struct mailimap_search_key * key_item);
665
666
667/*
668 this function creates an empty list of flags
669*/
670
671struct mailimap_flag_list *
672mailimap_flag_list_new_empty(void);
673
674/*
675 this function adds a flag to the list of flags
676
677 @return MAILIMAP_NO_ERROR will be returned on success,
678 other code will be returned otherwise
679*/
680
681int mailimap_flag_list_add(struct mailimap_flag_list * flag_list,
682 struct mailimap_flag * f);
683
684/*
685 this function creates a \Answered flag
686*/
687
688struct mailimap_flag * mailimap_flag_new_answered(void);
689
690/*
691 this function creates a \Flagged flag
692*/
693
694struct mailimap_flag * mailimap_flag_new_flagged(void);
695
696/*
697 this function creates a \Deleted flag
698*/
699
700struct mailimap_flag * mailimap_flag_new_deleted(void);
701
702/*
703 this function creates a \Seen flag
704*/
705
706struct mailimap_flag * mailimap_flag_new_seen(void);
707
708/*
709 this function creates a \Draft flag
710*/
711
712struct mailimap_flag * mailimap_flag_new_draft(void);
713
714/*
715 this function creates a keyword flag
716
717 @param flag_keyword this should be allocated with malloc()
718*/
719
720struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword);
721
722
723/*
724 this function creates an extension flag
725
726 @param flag_extension this should be allocated with malloc()
727*/
728
729struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension);
730
731/*
732 this function creates an empty list of status attributes
733*/
734
735struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void);
736
737/*
738 this function adds status attributes to the list
739
740 @return MAILIMAP_NO_ERROR will be returned on success,
741 other code will be returned otherwise
742*/
743
744int
745mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list,
746 int status_att);
747
748/* return mailimap_section_part from a given mailimap_body */
749
750int mailimap_get_section_part_from_body(struct mailimap_body * root_part,
751 struct mailimap_body * part,
752 struct mailimap_section_part ** result);
753
754#ifdef __cplusplus
755}
756#endif
757
758#endif
diff --git a/libetpan/include/libetpan/mailimf.h b/libetpan/include/libetpan/mailimf.h
new file mode 100644
index 0000000..c2231dd
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf.h
@@ -0,0 +1,347 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_H
37
38#define MAILIMF_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45#include <libetpan/mailimf_write_generic.h>
46#include <libetpan/mailimf_write_file.h>
47#include <libetpan/mailimf_write_mem.h>
48#include <libetpan/mailimf_types_helper.h>
49
50#include <inttypes.h>
51#include <sys/types.h>
52
53/*
54 mailimf_message_parse will parse the given message
55
56 @param message this is a string containing the message content
57 @param length this is the size of the given string
58 @param index this is a pointer to the start of the message in
59 the given string, (* index) is modified to point at the end
60 of the parsed data
61 @param result the result of the parse operation is stored in
62 (* result)
63
64 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
65*/
66
67int mailimf_message_parse(const char * message, size_t length,
68 size_t * index,
69 struct mailimf_message ** result);
70
71/*
72 mailimf_body_parse will parse the given text part of a message
73
74 @param message this is a string containing the message text part
75 @param length this is the size of the given string
76 @param index this is a pointer to the start of the message text part in
77 the given string, (* index) is modified to point at the end
78 of the parsed data
79 @param result the result of the parse operation is stored in
80 (* result)
81
82 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
83*/
84
85int mailimf_body_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailimf_body ** result);
88
89/*
90 mailimf_fields_parse will parse the given header fields
91
92 @param message this is a string containing the header fields
93 @param length this is the size of the given string
94 @param index this is a pointer to the start of the header fields in
95 the given string, (* index) is modified to point at the end
96 of the parsed data
97 @param result the result of the parse operation is stored in
98 (* result)
99
100 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
101*/
102
103int mailimf_fields_parse(const char * message, size_t length,
104 size_t * index,
105 struct mailimf_fields ** result);
106
107/*
108 mailimf_mailbox_list_parse will parse the given mailbox list
109
110 @param message this is a string containing the mailbox list
111 @param length this is the size of the given string
112 @param index this is a pointer to the start of the mailbox list in
113 the given string, (* index) is modified to point at the end
114 of the parsed data
115 @param result the result of the parse operation is stored in
116 (* result)
117
118 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
119*/
120
121int
122mailimf_mailbox_list_parse(const char * message, size_t length,
123 size_t * index,
124 struct mailimf_mailbox_list ** result);
125
126/*
127 mailimf_address_list_parse will parse the given address list
128
129 @param message this is a string containing the address list
130 @param length this is the size of the given string
131 @param index this is a pointer to the start of the address list in
132 the given string, (* index) is modified to point at the end
133 of the parsed data
134 @param result the result of the parse operation is stored in
135 (* result)
136
137 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
138*/
139
140int
141mailimf_address_list_parse(const char * message, size_t length,
142 size_t * index,
143 struct mailimf_address_list ** result);
144
145/*
146 mailimf_address_parse will parse the given address
147
148 @param message this is a string containing the address
149 @param length this is the size of the given string
150 @param index this is a pointer to the start of the address in
151 the given string, (* index) is modified to point at the end
152 of the parsed data
153 @param result the result of the parse operation is stored in
154 (* result)
155
156 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
157*/
158
159int mailimf_address_parse(const char * message, size_t length,
160 size_t * index,
161 struct mailimf_address ** result);
162
163/*
164 mailimf_mailbox_parse will parse the given address
165
166 @param message this is a string containing the mailbox
167 @param length this is the size of the given string
168 @param index this is a pointer to the start of the mailbox in
169 the given string, (* index) is modified to point at the end
170 of the parsed data
171 @param result the result of the parse operation is stored in
172 (* result)
173
174 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
175*/
176
177int mailimf_mailbox_parse(const char * message, size_t length,
178 size_t * index,
179 struct mailimf_mailbox ** result);
180
181/*
182 mailimf_date_time_parse will parse the given RFC 2822 date
183
184 @param message this is a string containing the date
185 @param length this is the size of the given string
186 @param index this is a pointer to the start of the date in
187 the given string, (* index) is modified to point at the end
188 of the parsed data
189 @param result the result of the parse operation is stored in
190 (* result)
191
192 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
193*/
194
195int mailimf_date_time_parse(const char * message, size_t length,
196 size_t * index,
197 struct mailimf_date_time ** result);
198
199/*
200 mailimf_envelope_fields_parse will parse the given fields (Date,
201 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
202 References and Subject)
203
204 @param message this is a string containing the header fields
205 @param length this is the size of the given string
206 @param index this is a pointer to the start of the header fields in
207 the given string, (* index) is modified to point at the end
208 of the parsed data
209 @param result the result of the parse operation is stored in
210 (* result)
211
212 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
213*/
214
215int mailimf_envelope_fields_parse(const char * message, size_t length,
216 size_t * index,
217 struct mailimf_fields ** result);
218
219/*
220 mailimf_ignore_field_parse will skip the given field
221
222 @param message this is a string containing the header field
223 @param length this is the size of the given string
224 @param index this is a pointer to the start of the header field in
225 the given string, (* index) is modified to point at the end
226 of the parsed data
227
228 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
229*/
230
231
232int mailimf_ignore_field_parse(const char * message, size_t length,
233 size_t * index);
234
235/*
236 mailimf_envelope_fields will parse the given fields (Date,
237 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
238 References and Subject), other fields will be added as optional
239 fields.
240
241 @param message this is a string containing the header fields
242 @param length this is the size of the given string
243 @param index this is a pointer to the start of the header fields in
244 the given string, (* index) is modified to point at the end
245 of the parsed data
246 @param result the result of the parse operation is stored in
247 (* result)
248
249 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
250*/
251
252
253int
254mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
255 size_t * index,
256 struct mailimf_fields ** result);
257
258/*
259 mailimf_envelope_fields will parse the given fields as optional
260 fields.
261
262 @param message this is a string containing the header fields
263 @param length this is the size of the given string
264 @param index this is a pointer to the start of the header fields in
265 the given string, (* index) is modified to point at the end
266 of the parsed data
267 @param result the result of the parse operation is stored in
268 (* result)
269
270 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
271*/
272
273int
274mailimf_optional_fields_parse(const char * message, size_t length,
275 size_t * index,
276 struct mailimf_fields ** result);
277
278
279/* internal use, exported for MIME */
280
281int mailimf_fws_parse(const char * message, size_t length, size_t * index);
282
283int mailimf_cfws_parse(const char * message, size_t length,
284 size_t * index);
285
286int mailimf_char_parse(const char * message, size_t length,
287 size_t * index, char token);
288
289int mailimf_unstrict_char_parse(const char * message, size_t length,
290 size_t * index, char token);
291
292int mailimf_crlf_parse(const char * message, size_t length, size_t * index);
293
294int
295mailimf_custom_string_parse(const char * message, size_t length,
296 size_t * index, char ** result,
297 int (* is_custom_char)(char));
298
299int
300mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
301 size_t * index, char * token,
302 size_t token_length);
303
304#define mailimf_token_case_insensitive_parse(message, length, index, token) \
305 mailimf_token_case_insensitive_len_parse(message, length, index, token, \
306 sizeof(token) - 1)
307
308int mailimf_quoted_string_parse(const char * message, size_t length,
309 size_t * index, char ** result);
310
311int
312mailimf_number_parse(const char * message, size_t length,
313 size_t * index, uint32_t * result);
314
315int mailimf_msg_id_parse(const char * message, size_t length,
316 size_t * index,
317 char ** result);
318
319int mailimf_msg_id_list_parse(const char * message, size_t length,
320 size_t * index, clist ** result);
321
322int mailimf_word_parse(const char * message, size_t length,
323 size_t * index, char ** result);
324
325int mailimf_atom_parse(const char * message, size_t length,
326 size_t * index, char ** result);
327
328int mailimf_fws_atom_parse(const char * message, size_t length,
329 size_t * index, char ** result);
330
331int mailimf_fws_word_parse(const char * message, size_t length,
332 size_t * index, char ** result);
333
334int mailimf_fws_quoted_string_parse(const char * message, size_t length,
335 size_t * index, char ** result);
336
337/* exported for IMAP */
338
339int mailimf_references_parse(const char * message, size_t length,
340 size_t * index,
341 struct mailimf_references ** result);
342
343#ifdef __cplusplus
344}
345#endif
346
347#endif
diff --git a/libetpan/include/libetpan/mailimf_types.h b/libetpan/include/libetpan/mailimf_types.h
new file mode 100644
index 0000000..e73db48
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf_types.h
@@ -0,0 +1,793 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32
33/*
34 * $Id$
35 */
36
37#ifndef MAILIMF_TYPES_H
38
39#define MAILIMF_TYPES_H
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45#include <libetpan/clist.h>
46#include <sys/types.h>
47
48/*
49 IMPORTANT NOTE:
50
51 All allocation functions will take as argument allocated data
52 and will store these data in the structure they will allocate.
53 Data should be persistant during all the use of the structure
54 and will be freed by the free function of the structure
55
56 allocation functions will return NULL on failure
57*/
58
59/*
60 mailimf_date_time is a date
61
62 - day is the day of month (1 to 31)
63
64 - month (1 to 12)
65
66 - year (4 digits)
67
68 - hour (0 to 23)
69
70 - min (0 to 59)
71
72 - sec (0 to 59)
73
74 - zone (this is the decimal value that we can read, for example:
75 for "-0200", the value is -200)
76*/
77
78struct mailimf_date_time {
79 int dt_day;
80 int dt_month;
81 int dt_year;
82 int dt_hour;
83 int dt_min;
84 int dt_sec;
85 int dt_zone;
86};
87
88struct mailimf_date_time *
89mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
90 int dt_hour, int dt_min, int dt_sec, int dt_zone);
91
92void mailimf_date_time_free(struct mailimf_date_time * date_time);
93
94
95
96/* this is the type of address */
97
98enum {
99 MAILIMF_ADDRESS_ERROR, /* on parse error */
100 MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */
101 MAILIMF_ADDRESS_GROUP, /* if this is a group
102 (group_name: address1@domain1,
103 address2@domain2; ) */
104};
105
106/*
107 mailimf_address is an address
108
109 - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP
110
111 - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX
112
113 - group is a group if type is MAILIMF_ADDRESS_GROUP
114*/
115
116struct mailimf_address {
117 int ad_type;
118 union {
119 struct mailimf_mailbox * ad_mailbox; /* can be NULL */
120 struct mailimf_group * ad_group; /* can be NULL */
121 } ad_data;
122};
123
124
125struct mailimf_address *
126mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
127 struct mailimf_group * ad_group);
128
129void mailimf_address_free(struct mailimf_address * address);
130
131
132
133/*
134 mailimf_mailbox is a mailbox
135
136 - display_name is the name that will be displayed for this mailbox,
137 for example 'name' in '"name" <mailbox@domain>,
138 should be allocated with malloc()
139
140 - addr_spec is the mailbox, for example 'mailbox@domain'
141 in '"name" <mailbox@domain>, should be allocated with malloc()
142*/
143
144struct mailimf_mailbox {
145 char * mb_display_name; /* can be NULL */
146 char * mb_addr_spec; /* != NULL */
147};
148
149struct mailimf_mailbox *
150mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec);
151
152void mailimf_mailbox_free(struct mailimf_mailbox * mailbox);
153
154
155
156/*
157 mailimf_group is a group
158
159 - display_name is the name that will be displayed for this group,
160 for example 'group_name' in
161 'group_name: address1@domain1, address2@domain2;', should be allocated
162 with malloc()
163
164 - mb_list is a list of mailboxes
165*/
166
167struct mailimf_group {
168 char * grp_display_name; /* != NULL */
169 struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
170};
171
172struct mailimf_group *
173mailimf_group_new(char * grp_display_name,
174 struct mailimf_mailbox_list * grp_mb_list);
175
176void mailimf_group_free(struct mailimf_group * group);
177
178
179
180/*
181 mailimf_mailbox_list is a list of mailboxes
182
183 - list is a list of mailboxes
184*/
185
186struct mailimf_mailbox_list {
187 clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */
188};
189
190struct mailimf_mailbox_list *
191mailimf_mailbox_list_new(clist * mb_list);
192
193void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);
194
195
196
197/*
198 mailimf_address_list is a list of addresses
199
200 - list is a list of addresses
201*/
202
203struct mailimf_address_list {
204 clist * ad_list; /* list of (struct mailimf_address *), != NULL */
205};
206
207struct mailimf_address_list *
208mailimf_address_list_new(clist * ad_list);
209
210void mailimf_address_list_free(struct mailimf_address_list * addr_list);
211
212
213
214
215
216/*
217 mailimf_body is the text part of a message
218
219 - text is the beginning of the text part, it is a substring
220 of an other string
221
222 - size is the size of the text part
223*/
224
225struct mailimf_body {
226 const char * bd_text; /* != NULL */
227 size_t bd_size;
228};
229
230struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);
231
232void mailimf_body_free(struct mailimf_body * body);
233
234
235
236
237/*
238 mailimf_message is the content of the message
239
240 - msg_fields is the header fields of the message
241
242 - msg_body is the text part of the message
243*/
244
245struct mailimf_message {
246 struct mailimf_fields * msg_fields; /* != NULL */
247 struct mailimf_body * msg_body; /* != NULL */
248};
249
250struct mailimf_message *
251mailimf_message_new(struct mailimf_fields * msg_fields,
252 struct mailimf_body * msg_body);
253
254void mailimf_message_free(struct mailimf_message * message);
255
256
257
258
259/*
260 mailimf_fields is a list of header fields
261
262 - fld_list is a list of header fields
263*/
264
265struct mailimf_fields {
266 clist * fld_list; /* list of (struct mailimf_field *), != NULL */
267};
268
269struct mailimf_fields * mailimf_fields_new(clist * fld_list);
270
271void mailimf_fields_free(struct mailimf_fields * fields);
272
273
274
275/* this is a type of field */
276
277enum {
278 MAILIMF_FIELD_NONE, /* on parse error */
279 MAILIMF_FIELD_RETURN_PATH, /* Return-Path */
280 MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */
281 MAILIMF_FIELD_RESENT_FROM, /* Resent-From */
282 MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */
283 MAILIMF_FIELD_RESENT_TO, /* Resent-To */
284 MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */
285 MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */
286 MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */
287 MAILIMF_FIELD_ORIG_DATE, /* Date */
288 MAILIMF_FIELD_FROM, /* From */
289 MAILIMF_FIELD_SENDER, /* Sender */
290 MAILIMF_FIELD_REPLY_TO, /* Reply-To */
291 MAILIMF_FIELD_TO, /* To */
292 MAILIMF_FIELD_CC, /* Cc */
293 MAILIMF_FIELD_BCC, /* Bcc */
294 MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */
295 MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */
296 MAILIMF_FIELD_REFERENCES, /* References */
297 MAILIMF_FIELD_SUBJECT, /* Subject */
298 MAILIMF_FIELD_COMMENTS, /* Comments */
299 MAILIMF_FIELD_KEYWORDS, /* Keywords */
300 MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
301};
302
303/*
304 mailimf_field is a field
305
306 - fld_type is the type of the field
307
308 - fld_data.fld_return_path is the parsed content of the Return-Path
309 field if type is MAILIMF_FIELD_RETURN_PATH
310
311 - fld_data.fld_resent_date is the parsed content of the Resent-Date field
312 if type is MAILIMF_FIELD_RESENT_DATE
313
314 - fld_data.fld_resent_from is the parsed content of the Resent-From field
315
316 - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field
317
318 - fld_data.fld_resent_to is the parsed content of the Resent-To field
319
320 - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field
321
322 - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field
323
324 - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID
325 field
326
327 - fld_data.fld_orig_date is the parsed content of the Date field
328
329 - fld_data.fld_from is the parsed content of the From field
330
331 - fld_data.fld_sender is the parsed content of the Sender field
332
333 - fld_data.fld_reply_to is the parsed content of the Reply-To field
334
335 - fld_data.fld_to is the parsed content of the To field
336
337 - fld_data.fld_cc is the parsed content of the Cc field
338
339 - fld_data.fld_bcc is the parsed content of the Bcc field
340
341 - fld_data.fld_message_id is the parsed content of the Message-ID field
342
343 - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field
344
345 - fld_data.fld_references is the parsed content of the References field
346
347 - fld_data.fld_subject is the content of the Subject field
348
349 - fld_data.fld_comments is the content of the Comments field
350
351 - fld_data.fld_keywords is the parsed content of the Keywords field
352
353 - fld_data.fld_optional_field is an other field and is not parsed
354*/
355
356#define LIBETPAN_MAILIMF_FIELD_UNION
357
358struct mailimf_field {
359 int fld_type;
360 union {
361 struct mailimf_return * fld_return_path; /* can be NULL */
362 struct mailimf_orig_date * fld_resent_date; /* can be NULL */
363 struct mailimf_from * fld_resent_from; /* can be NULL */
364 struct mailimf_sender * fld_resent_sender; /* can be NULL */
365 struct mailimf_to * fld_resent_to; /* can be NULL */
366 struct mailimf_cc * fld_resent_cc; /* can be NULL */
367 struct mailimf_bcc * fld_resent_bcc; /* can be NULL */
368 struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
369 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
370 struct mailimf_from * fld_from; /* can be NULL */
371 struct mailimf_sender * fld_sender; /* can be NULL */
372 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
373 struct mailimf_to * fld_to; /* can be NULL */
374 struct mailimf_cc * fld_cc; /* can be NULL */
375 struct mailimf_bcc * fld_bcc; /* can be NULL */
376 struct mailimf_message_id * fld_message_id; /* can be NULL */
377 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
378 struct mailimf_references * fld_references; /* can be NULL */
379 struct mailimf_subject * fld_subject; /* can be NULL */
380 struct mailimf_comments * fld_comments; /* can be NULL */
381 struct mailimf_keywords * fld_keywords; /* can be NULL */
382 struct mailimf_optional_field * fld_optional_field; /* can be NULL */
383 } fld_data;
384};
385
386struct mailimf_field *
387mailimf_field_new(int fld_type,
388 struct mailimf_return * fld_return_path,
389 struct mailimf_orig_date * fld_resent_date,
390 struct mailimf_from * fld_resent_from,
391 struct mailimf_sender * fld_resent_sender,
392 struct mailimf_to * fld_resent_to,
393 struct mailimf_cc * fld_resent_cc,
394 struct mailimf_bcc * fld_resent_bcc,
395 struct mailimf_message_id * fld_resent_msg_id,
396 struct mailimf_orig_date * fld_orig_date,
397 struct mailimf_from * fld_from,
398 struct mailimf_sender * fld_sender,
399 struct mailimf_reply_to * fld_reply_to,
400 struct mailimf_to * fld_to,
401 struct mailimf_cc * fld_cc,
402 struct mailimf_bcc * fld_bcc,
403 struct mailimf_message_id * fld_message_id,
404 struct mailimf_in_reply_to * fld_in_reply_to,
405 struct mailimf_references * fld_references,
406 struct mailimf_subject * fld_subject,
407 struct mailimf_comments * fld_comments,
408 struct mailimf_keywords * fld_keywords,
409 struct mailimf_optional_field * fld_optional_field);
410
411void mailimf_field_free(struct mailimf_field * field);
412
413
414
415/*
416 mailimf_orig_date is the parsed Date field
417
418 - date_time is the parsed date
419*/
420
421struct mailimf_orig_date {
422 struct mailimf_date_time * dt_date_time; /* != NULL */
423};
424
425struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
426 dt_date_time);
427
428void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);
429
430
431
432
433/*
434 mailimf_from is the parsed From field
435
436 - mb_list is the parsed mailbox list
437*/
438
439struct mailimf_from {
440 struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
441};
442
443struct mailimf_from *
444mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);
445
446void mailimf_from_free(struct mailimf_from * from);
447
448
449
450/*
451 mailimf_sender is the parsed Sender field
452
453 - snd_mb is the parsed mailbox
454*/
455
456struct mailimf_sender {
457 struct mailimf_mailbox * snd_mb; /* != NULL */
458};
459
460struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);
461
462void mailimf_sender_free(struct mailimf_sender * sender);
463
464
465
466
467/*
468 mailimf_reply_to is the parsed Reply-To field
469
470 - rt_addr_list is the parsed address list
471 */
472
473struct mailimf_reply_to {
474 struct mailimf_address_list * rt_addr_list; /* != NULL */
475};
476
477struct mailimf_reply_to *
478mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);
479
480void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);
481
482
483
484
485/*
486 mailimf_to is the parsed To field
487
488 - to_addr_list is the parsed address list
489*/
490
491struct mailimf_to {
492 struct mailimf_address_list * to_addr_list; /* != NULL */
493};
494
495struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);
496
497void mailimf_to_free(struct mailimf_to * to);
498
499
500
501
502/*
503 mailimf_cc is the parsed Cc field
504
505 - cc_addr_list is the parsed addres list
506*/
507
508struct mailimf_cc {
509 struct mailimf_address_list * cc_addr_list; /* != NULL */
510};
511
512struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list);
513
514void mailimf_cc_free(struct mailimf_cc * cc);
515
516
517
518
519/*
520 mailimf_bcc is the parsed Bcc field
521
522 - bcc_addr_list is the parsed addres list
523*/
524
525struct mailimf_bcc {
526 struct mailimf_address_list * bcc_addr_list; /* can be NULL */
527};
528
529struct mailimf_bcc *
530mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);
531
532void mailimf_bcc_free(struct mailimf_bcc * bcc);
533
534
535
536/*
537 mailimf_message_id is the parsed Message-ID field
538
539 - mid_value is the message identifier
540*/
541
542struct mailimf_message_id {
543 char * mid_value; /* != NULL */
544};
545
546struct mailimf_message_id * mailimf_message_id_new(char * mid_value);
547
548void mailimf_message_id_free(struct mailimf_message_id * message_id);
549
550
551
552
553/*
554 mailimf_in_reply_to is the parsed In-Reply-To field
555
556 - mid_list is the list of message identifers
557*/
558
559struct mailimf_in_reply_to {
560 clist * mid_list; /* list of (char *), != NULL */
561};
562
563struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);
564
565void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);
566
567
568
569/*
570 mailimf_references is the parsed References field
571
572 - msg_id_list is the list of message identifiers
573 */
574
575struct mailimf_references {
576 clist * mid_list; /* list of (char *) */
577 /* != NULL */
578};
579
580struct mailimf_references * mailimf_references_new(clist * mid_list);
581
582void mailimf_references_free(struct mailimf_references * references);
583
584
585
586/*
587 mailimf_subject is the parsed Subject field
588
589 - sbj_value is the value of the field
590*/
591
592struct mailimf_subject {
593 char * sbj_value; /* != NULL */
594};
595
596struct mailimf_subject * mailimf_subject_new(char * sbj_value);
597
598void mailimf_subject_free(struct mailimf_subject * subject);
599
600
601/*
602 mailimf_comments is the parsed Comments field
603
604 - cm_value is the value of the field
605*/
606
607struct mailimf_comments {
608 char * cm_value; /* != NULL */
609};
610
611struct mailimf_comments * mailimf_comments_new(char * cm_value);
612
613void mailimf_comments_free(struct mailimf_comments * comments);
614
615
616/*
617 mailimf_keywords is the parsed Keywords field
618
619 - kw_list is the list of keywords
620*/
621
622struct mailimf_keywords {
623 clist * kw_list; /* list of (char *), != NULL */
624};
625
626struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);
627
628void mailimf_keywords_free(struct mailimf_keywords * keywords);
629
630
631/*
632 mailimf_return is the parsed Return-Path field
633
634 - ret_path is the parsed value of Return-Path
635*/
636
637struct mailimf_return {
638 struct mailimf_path * ret_path; /* != NULL */
639};
640
641struct mailimf_return *
642mailimf_return_new(struct mailimf_path * ret_path);
643
644void mailimf_return_free(struct mailimf_return * return_path);
645
646
647/*
648 mailimf_path is the parsed value of Return-Path
649
650 - pt_addr_spec is a mailbox
651*/
652
653struct mailimf_path {
654 char * pt_addr_spec; /* can be NULL */
655};
656
657struct mailimf_path * mailimf_path_new(char * pt_addr_spec);
658
659void mailimf_path_free(struct mailimf_path * path);
660
661
662/*
663 mailimf_optional_field is a non-parsed field
664
665 - fld_name is the name of the field
666
667 - fld_value is the value of the field
668*/
669
670struct mailimf_optional_field {
671 char * fld_name; /* != NULL */
672 char * fld_value; /* != NULL */
673};
674
675struct mailimf_optional_field *
676mailimf_optional_field_new(char * fld_name, char * fld_value);
677
678void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);
679
680
681/*
682 mailimf_fields is the native structure that IMF module will use,
683 this module will provide an easier structure to use when parsing fields.
684
685 mailimf_single_fields is an easier structure to get parsed fields,
686 rather than iteration over the list of fields
687
688 - fld_orig_date is the parsed "Date" field
689
690 - fld_from is the parsed "From" field
691
692 - fld_sender is the parsed "Sender "field
693
694 - fld_reply_to is the parsed "Reply-To" field
695
696 - fld_to is the parsed "To" field
697
698 - fld_cc is the parsed "Cc" field
699
700 - fld_bcc is the parsed "Bcc" field
701
702 - fld_message_id is the parsed "Message-ID" field
703
704 - fld_in_reply_to is the parsed "In-Reply-To" field
705
706 - fld_references is the parsed "References" field
707
708 - fld_subject is the parsed "Subject" field
709
710 - fld_comments is the parsed "Comments" field
711
712 - fld_keywords is the parsed "Keywords" field
713*/
714
715struct mailimf_single_fields {
716 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
717 struct mailimf_from * fld_from; /* can be NULL */
718 struct mailimf_sender * fld_sender; /* can be NULL */
719 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
720 struct mailimf_to * fld_to; /* can be NULL */
721 struct mailimf_cc * fld_cc; /* can be NULL */
722 struct mailimf_bcc * fld_bcc; /* can be NULL */
723 struct mailimf_message_id * fld_message_id; /* can be NULL */
724 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
725 struct mailimf_references * fld_references; /* can be NULL */
726 struct mailimf_subject * fld_subject; /* can be NULL */
727 struct mailimf_comments * fld_comments; /* can be NULL */
728 struct mailimf_keywords * fld_keywords; /* can be NULL */
729};
730
731
732
733
734
735
736/* internal use */
737
738void mailimf_atom_free(char * atom);
739
740void mailimf_dot_atom_free(char * dot_atom);
741
742void mailimf_dot_atom_text_free(char * dot_atom);
743
744void mailimf_quoted_string_free(char * quoted_string);
745
746void mailimf_word_free(char * word);
747
748void mailimf_phrase_free(char * phrase);
749
750void mailimf_unstructured_free(char * unstructured);
751
752void mailimf_angle_addr_free(char * angle_addr);
753
754void mailimf_display_name_free(char * display_name);
755
756void mailimf_addr_spec_free(char * addr_spec);
757
758void mailimf_local_part_free(char * local_part);
759
760void mailimf_domain_free(char * domain);
761
762void mailimf_domain_literal_free(char * domain);
763
764void mailimf_msg_id_free(char * msg_id);
765
766void mailimf_id_left_free(char * id_left);
767
768void mailimf_id_right_free(char * id_right);
769
770void mailimf_no_fold_quote_free(char * nfq);
771
772void mailimf_no_fold_literal_free(char * nfl);
773
774void mailimf_field_name_free(char * field_name);
775
776
777
778/* these are the possible returned error codes */
779
780enum {
781 MAILIMF_NO_ERROR = 0,
782 MAILIMF_ERROR_PARSE,
783 MAILIMF_ERROR_MEMORY,
784 MAILIMF_ERROR_INVAL,
785 MAILIMF_ERROR_FILE,
786};
787
788
789#ifdef __cplusplus
790}
791#endif
792
793#endif
diff --git a/libetpan/include/libetpan/mailimf_types_helper.h b/libetpan/include/libetpan/mailimf_types_helper.h
new file mode 100644
index 0000000..337b1d0
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf_types_helper.h
@@ -0,0 +1,370 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_TYPES_HELPER
37
38#define MAILIMF_TYPES_HELPER
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45
46/*
47 IMPORTANT NOTE:
48
49 All allocation functions will take as argument allocated data
50 and will store these data in the structure they will allocate.
51 Data should be persistant during all the use of the structure
52 and will be freed by the free function of the structure
53
54 allocation functions will return NULL on failure
55*/
56
57/*
58 mailimf_mailbox_list_new_empty creates an empty list of mailboxes
59*/
60
61struct mailimf_mailbox_list *
62mailimf_mailbox_list_new_empty();
63
64/*
65 mailimf_mailbox_list_add adds a mailbox to the list of mailboxes
66
67 @return MAILIMF_NO_ERROR will be returned on success,
68 other code will be returned otherwise
69*/
70
71int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
72 struct mailimf_mailbox * mb);
73
74/*
75 mailimf_mailbox_list_add_parse parse the given string
76 into a mailimf_mailbox structure and adds it to the list of mailboxes
77
78 @return MAILIMF_NO_ERROR will be returned on success,
79 other code will be returned otherwise
80*/
81
82int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
83 char * mb_str);
84
85/*
86 mailimf_mailbox creates a mailimf_mailbox structure with the given
87 arguments and adds it to the list of mailboxes
88
89 - display_name is the name that will be displayed for this mailbox,
90 for example 'name' in '"name" <mailbox@domain>,
91 should be allocated with malloc()
92
93 - address is the mailbox, for example 'mailbox@domain'
94 in '"name" <mailbox@domain>, should be allocated with malloc()
95
96 @return MAILIMF_NO_ERROR will be returned on success,
97 other code will be returned otherwise
98*/
99
100int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
101 char * display_name, char * address);
102
103/*
104 mailimf_address_list_new_empty creates an empty list of addresses
105*/
106
107struct mailimf_address_list *
108mailimf_address_list_new_empty();
109
110/*
111 mailimf_address_list_add adds a mailbox to the list of addresses
112
113 @return MAILIMF_NO_ERROR will be returned on success,
114 other code will be returned otherwise
115*/
116
117int mailimf_address_list_add(struct mailimf_address_list * address_list,
118 struct mailimf_address * addr);
119
120/*
121 mailimf_address_list_add_parse parse the given string
122 into a mailimf_address structure and adds it to the list of addresses
123
124 @return MAILIMF_NO_ERROR will be returned on success,
125 other code will be returned otherwise
126*/
127
128int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
129 char * addr_str);
130
131/*
132 mailimf_address_list_add_mb creates a mailbox mailimf_address
133 with the given arguments and adds it to the list of addresses
134
135 - display_name is the name that will be displayed for this mailbox,
136 for example 'name' in '"name" <mailbox@domain>,
137 should be allocated with malloc()
138
139 - address is the mailbox, for example 'mailbox@domain'
140 in '"name" <mailbox@domain>, should be allocated with malloc()
141
142 @return MAILIMF_NO_ERROR will be returned on success,
143 other code will be returned otherwise
144*/
145
146int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
147 char * display_name, char * address);
148
149/*
150 mailimf_resent_fields_add_data adds a set of resent fields in the
151 given mailimf_fields structure.
152
153 if you don't want a given field in the set to be added in the list
154 of fields, you can give NULL as argument
155
156 @param resent_msg_id sould be allocated with malloc()
157
158 @return MAILIMF_NO_ERROR will be returned on success,
159 other code will be returned otherwise
160*/
161
162int
163mailimf_resent_fields_add_data(struct mailimf_fields * fields,
164 struct mailimf_date_time * resent_date,
165 struct mailimf_mailbox_list * resent_from,
166 struct mailimf_mailbox * resent_sender,
167 struct mailimf_address_list * resent_to,
168 struct mailimf_address_list * resent_cc,
169 struct mailimf_address_list * resent_bcc,
170 char * resent_msg_id);
171
172/*
173 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
174 structure with a set of resent fields
175
176 if you don't want a given field in the set to be added in the list
177 of fields, you can give NULL as argument
178
179 @param resent_msg_id sould be allocated with malloc()
180
181 @return MAILIMF_NO_ERROR will be returned on success,
182 other code will be returned otherwise
183*/
184
185struct mailimf_fields *
186mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
187 resent_date, struct mailimf_mailbox_list * resent_from,
188 struct mailimf_mailbox * resent_sender,
189 struct mailimf_address_list * resent_to,
190 struct mailimf_address_list * resent_cc,
191 struct mailimf_address_list * resent_bcc,
192 char * resent_msg_id);
193
194/*
195 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
196 structure with a set of resent fields.
197 Resent-Date and Resent-Message-ID fields will be generated for you.
198
199 if you don't want a given field in the set to be added in the list
200 of fields, you can give NULL as argument
201
202 @return MAILIMF_NO_ERROR will be returned on success,
203 other code will be returned otherwise
204*/
205
206struct mailimf_fields *
207mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
208 struct mailimf_mailbox * sender,
209 struct mailimf_address_list * to,
210 struct mailimf_address_list * cc,
211 struct mailimf_address_list * bcc);
212
213/*
214 this function creates a new mailimf_fields structure with no fields
215*/
216
217struct mailimf_fields *
218mailimf_fields_new_empty(void);
219
220
221/*
222 this function adds a field to the mailimf_fields structure
223
224 @return MAILIMF_NO_ERROR will be returned on success,
225 other code will be returned otherwise
226*/
227
228int mailimf_fields_add(struct mailimf_fields * fields,
229 struct mailimf_field * field);
230
231
232/*
233 mailimf_fields_add_data adds a set of fields in the
234 given mailimf_fields structure.
235
236 if you don't want a given field in the set to be added in the list
237 of fields, you can give NULL as argument
238
239 @param msg_id sould be allocated with malloc()
240 @param subject should be allocated with malloc()
241 @param in_reply_to each elements of this list should be allocated
242 with malloc()
243 @param references each elements of this list should be allocated
244 with malloc()
245
246 @return MAILIMF_NO_ERROR will be returned on success,
247 other code will be returned otherwise
248*/
249
250int mailimf_fields_add_data(struct mailimf_fields * fields,
251 struct mailimf_date_time * date,
252 struct mailimf_mailbox_list * from,
253 struct mailimf_mailbox * sender,
254 struct mailimf_address_list * reply_to,
255 struct mailimf_address_list * to,
256 struct mailimf_address_list * cc,
257 struct mailimf_address_list * bcc,
258 char * msg_id,
259 clist * in_reply_to,
260 clist * references,
261 char * subject);
262
263/*
264 mailimf_fields_new_with_data_all creates a new mailimf_fields
265 structure with a set of fields
266
267 if you don't want a given field in the set to be added in the list
268 of fields, you can give NULL as argument
269
270 @param message_id sould be allocated with malloc()
271 @param subject should be allocated with malloc()
272 @param in_reply_to each elements of this list should be allocated
273 with malloc()
274 @param references each elements of this list should be allocated
275 with malloc()
276
277 @return MAILIMF_NO_ERROR will be returned on success,
278 other code will be returned otherwise
279*/
280
281struct mailimf_fields *
282mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
283 struct mailimf_mailbox_list * from,
284 struct mailimf_mailbox * sender,
285 struct mailimf_address_list * reply_to,
286 struct mailimf_address_list * to,
287 struct mailimf_address_list * cc,
288 struct mailimf_address_list * bcc,
289 char * message_id,
290 clist * in_reply_to,
291 clist * references,
292 char * subject);
293
294/*
295 mailimf_fields_new_with_data creates a new mailimf_fields
296 structure with a set of fields
297 Date and Message-ID fields will be generated for you.
298
299 if you don't want a given field in the set to be added in the list
300 of fields, you can give NULL as argument
301
302 @param subject should be allocated with malloc()
303 @param in_reply_to each elements of this list should be allocated
304 with malloc()
305 @param references each elements of this list should be allocated
306 with malloc()
307
308 @return MAILIMF_NO_ERROR will be returned on success,
309 other code will be returned otherwise
310*/
311
312struct mailimf_fields *
313mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
314 struct mailimf_mailbox * sender,
315 struct mailimf_address_list * reply_to,
316 struct mailimf_address_list * to,
317 struct mailimf_address_list * cc,
318 struct mailimf_address_list * bcc,
319 clist * in_reply_to,
320 clist * references,
321 char * subject);
322
323/*
324 this function returns an allocated message identifier to
325 use in a Message-ID or Resent-Message-ID field
326*/
327
328char * mailimf_get_message_id(void);
329
330/*
331 this function returns a mailimf_date_time structure to
332 use in a Date or Resent-Date field
333*/
334
335struct mailimf_date_time * mailimf_get_current_date(void);
336
337
338/*
339 mailimf_single_fields_init fills a mailimf_single_fields structure
340 with the content of a mailimf_fields structure
341*/
342
343void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
344 struct mailimf_fields * fields);
345
346/*
347 mailimf_single_fields_new creates a new mailimf_single_fields and
348 fills the structure with mailimf_fields
349*/
350
351struct mailimf_single_fields *
352mailimf_single_fields_new(struct mailimf_fields * fields);
353
354void mailimf_single_fields_free(struct mailimf_single_fields *
355 single_fields);
356
357/*
358 mailimf_field_new_custom creates a new field of type optional
359
360 @param name should be allocated with malloc()
361 @param value should be allocated with malloc()
362*/
363
364struct mailimf_field * mailimf_field_new_custom(char * name, char * value);
365
366#ifdef __cplusplus
367}
368#endif
369
370#endif
diff --git a/libetpan/include/libetpan/mailimf_write_file.h b/libetpan/include/libetpan/mailimf_write_file.h
new file mode 100644
index 0000000..2b7707f
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf_write_file.h
@@ -0,0 +1,169 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_H
37
38#define MAILIMF_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47 //#define MAILIMF_WRITE_COMPATIBILITY
48
49/*
50 mailimf_string_write_file writes a string to a given stream
51
52 @param f is the stream
53 @param col (* col) is the column number where we will start to
54 write the text, the ending column will be stored in (* col)
55 @param str is the string to write
56*/
57
58int mailimf_string_write_file(FILE * f, int * col,
59 const char * str, size_t length);
60
61
62/*
63 mailimf_fields_write_file writes the fields to a given stream
64
65 @param f is the stream
66 @param col (* col) is the column number where we will start to
67 write the text, the ending column will be stored in (* col)
68 @param fields is the fields to write
69*/
70
71int mailimf_fields_write_file(FILE * f, int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write_file writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_file(FILE * f, int * col,
85 struct mailimf_fields * fields);
86
87
88/*
89 mailimf_field_write_file writes a field to a given stream
90
91 @param f is the stream
92 @param col (* col) is the column number where we will start to
93 write the text, the ending column will be stored in (* col)
94 @param field is the field to write
95*/
96
97int mailimf_field_write_file(FILE * f, int * col,
98 struct mailimf_field * field);
99
100/*
101 mailimf_quoted_string_write_file writes a string that is quoted
102 to a given stream
103
104 @param f is the stream
105 @param col (* col) is the column number where we will start to
106 write the text, the ending column will be stored in (* col)
107 @param string is the string to quote and write
108*/
109
110int mailimf_quoted_string_write_file(FILE * f, int * col,
111 const char * string, size_t len);
112
113int mailimf_address_list_write_file(FILE * f, int * col,
114 struct mailimf_address_list * addr_list);
115
116int mailimf_mailbox_list_write_file(FILE * f, int * col,
117 struct mailimf_mailbox_list * mb_list);
118
119/*
120 mailimf_header_string_write_file writes a header value and fold the header
121 if needed.
122
123 @param f is the stream
124 @param col (* col) is the column number where we will start to
125 write the text, the ending column will be stored in (* col)
126 @param str is the string to write
127*/
128
129int mailimf_header_string_write_file(FILE * f, int * col,
130 const char * str, size_t length);
131
132
133
134/* binary compatibility with 0.34 - begin */
135
136#ifdef MAILIMF_WRITE_COMPATIBILITY
137int mailimf_string_write(FILE * f, int * col,
138 const char * str, size_t length);
139
140int mailimf_fields_write(FILE * f, int * col,
141 struct mailimf_fields * fields);
142
143int mailimf_envelope_fields_write(FILE * f, int * col,
144 struct mailimf_fields * fields);
145
146int mailimf_field_write(FILE * f, int * col,
147 struct mailimf_field * field);
148
149int mailimf_quoted_string_write(FILE * f, int * col,
150 const char * string, size_t len);
151
152int mailimf_address_list_write(FILE * f, int * col,
153 struct mailimf_address_list * addr_list);
154
155int mailimf_mailbox_list_write(FILE * f, int * col,
156 struct mailimf_mailbox_list * mb_list);
157
158int mailimf_header_string_write(FILE * f, int * col,
159 const char * str, size_t length);
160#endif
161
162/* binary compatibility with 0.34 - end */
163
164
165#ifdef __cplusplus
166}
167#endif
168
169#endif
diff --git a/libetpan/include/libetpan/mailimf_write_generic.h b/libetpan/include/libetpan/mailimf_write_generic.h
new file mode 100644
index 0000000..c207d7e
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf_write_generic.h
@@ -0,0 +1,142 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_GENERIC_H
37
38#define MAILIMF_WRITE_GENERIC_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47/*
48 mailimf_string_write writes a string to a given stream
49
50 @param f is the stream
51 @param col (* col) is the column number where we will start to
52 write the text, the ending column will be stored in (* col)
53 @param str is the string to write
54*/
55
56int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
57 int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write writes the fields to a given stream
63
64 @param f is the stream
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
71 int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
85 int * col,
86 struct mailimf_fields * fields);
87
88
89/*
90 mailimf_field_write writes a field to a given stream
91
92 @param f is the stream
93 @param col (* col) is the column number where we will start to
94 write the text, the ending column will be stored in (* col)
95 @param field is the field to write
96*/
97
98int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
99 int * col,
100 struct mailimf_field * field);
101
102/*
103 mailimf_quoted_string_write writes a string that is quoted
104 to a given stream
105
106 @param f is the stream
107 @param col (* col) is the column number where we will start to
108 write the text, the ending column will be stored in (* col)
109 @param string is the string to quote and write
110*/
111
112int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
113 int * col,
114 const char * string, size_t len);
115
116int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
117 int * col,
118 struct mailimf_address_list * addr_list);
119
120int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
121 int * col,
122 struct mailimf_mailbox_list * mb_list);
123
124/*
125 mailimf_header_string_write writes a header value and fold the header
126 if needed.
127
128 @param f is the stream
129 @param col (* col) is the column number where we will start to
130 write the text, the ending column will be stored in (* col)
131 @param str is the string to write
132*/
133
134int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
135 int * col,
136 const char * str, size_t length);
137
138#ifdef __cplusplus
139}
140#endif
141
142#endif
diff --git a/libetpan/include/libetpan/mailimf_write_mem.h b/libetpan/include/libetpan/mailimf_write_mem.h
new file mode 100644
index 0000000..796f178
--- a/dev/null
+++ b/libetpan/include/libetpan/mailimf_write_mem.h
@@ -0,0 +1,135 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_MEM_H
37
38#define MAILIMF_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46#include <libetpan/mmapstring.h>
47
48/*
49 mailimf_string_write_mem appends a string to a given string
50
51 @param f is the string
52 @param col (* col) is the column number where we will start to
53 write the text, the ending column will be stored in (* col)
54 @param str is the string to write
55*/
56
57int mailimf_string_write_mem(MMAPString * f, int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write_mem appends the fields to a given string
63
64 @param f is the string
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_mem(MMAPString * f, int * col,
71 struct mailimf_fields * fields);
72
73
74/*
75 mailimf_envelope_fields_write_mem appends some fields to a given string
76
77 @param f is the string
78 @param col (* col) is the column number where we will start to
79 write the text, the ending column will be stored in (* col)
80 @param fields is the fields to write
81*/
82
83int mailimf_envelope_fields_write_mem(MMAPString * f, int * col,
84 struct mailimf_fields * fields);
85
86
87/*
88 mailimf_field_write_mem appends a field to a given string
89
90 @param f is the string
91 @param col (* col) is the column number where we will start to
92 write the text, the ending column will be stored in (* col)
93 @param field is the field to write
94*/
95
96int mailimf_field_write_mem(MMAPString * f, int * col,
97 struct mailimf_field * field);
98
99/*
100 mailimf_quoted_string_write_mem appends a string that is quoted
101 to a given string
102
103 @param f is the string
104 @param col (* col) is the column number where we will start to
105 write the text, the ending column will be stored in (* col)
106 @param string is the string to quote and write
107*/
108
109int mailimf_quoted_string_write_mem(MMAPString * f, int * col,
110 const char * string, size_t len);
111
112int mailimf_address_list_write_mem(MMAPString * f, int * col,
113 struct mailimf_address_list * addr_list);
114
115int mailimf_mailbox_list_write_mem(MMAPString * f, int * col,
116 struct mailimf_mailbox_list * mb_list);
117
118/*
119 mailimf_header_string_write_mem appends a header value and fold the header
120 if needed.
121
122 @param f is the string
123 @param col (* col) is the column number where we will start to
124 write the text, the ending column will be stored in (* col)
125 @param str is the string to write
126*/
127
128int mailimf_header_string_write_mem(MMAPString * f, int * col,
129 const char * str, size_t length);
130
131#ifdef __cplusplus
132}
133#endif
134
135#endif
diff --git a/libetpan/include/libetpan/mailmbox.h b/libetpan/include/libetpan/mailmbox.h
new file mode 100644
index 0000000..ea21d48
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmbox.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMBOX_H
37
38#define MAILMBOX_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmbox_types.h>
45
46int
47mailmbox_append_message_list(struct mailmbox_folder * folder,
48 carray * append_tab);
49
50int
51mailmbox_append_message(struct mailmbox_folder * folder,
52 const char * data, size_t len);
53
54int
55mailmbox_append_message_uid(struct mailmbox_folder * folder,
56 const char * data, size_t len, unsigned int * puid);
57
58int mailmbox_fetch_msg(struct mailmbox_folder * folder,
59 uint32_t num, char ** result,
60 size_t * result_len);
61
62int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder,
63 uint32_t num, char ** result,
64 size_t * result_len);
65
66void mailmbox_fetch_result_free(char * msg);
67
68int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder,
69 struct mailmbox_folder * src_folder,
70 carray * tab);
71
72int mailmbox_copy_msg(struct mailmbox_folder * dest_folder,
73 struct mailmbox_folder * src_folder,
74 uint32_t uid);
75
76int mailmbox_expunge(struct mailmbox_folder * folder);
77
78int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid);
79
80int mailmbox_init(const char * filename,
81 int force_readonly,
82 int force_no_uid,
83 uint32_t default_written_uid,
84 struct mailmbox_folder ** result_folder);
85
86void mailmbox_done(struct mailmbox_folder * folder);
87
88/* low-level access primitives */
89
90int mailmbox_write_lock(struct mailmbox_folder * folder);
91
92int mailmbox_write_unlock(struct mailmbox_folder * folder);
93
94int mailmbox_read_lock(struct mailmbox_folder * folder);
95
96int mailmbox_read_unlock(struct mailmbox_folder * folder);
97
98
99/* memory map */
100
101int mailmbox_map(struct mailmbox_folder * folder);
102
103void mailmbox_unmap(struct mailmbox_folder * folder);
104
105void mailmbox_sync(struct mailmbox_folder * folder);
106
107
108/* open & close file */
109
110int mailmbox_open(struct mailmbox_folder * folder);
111
112void mailmbox_close(struct mailmbox_folder * folder);
113
114
115/* validate cache */
116
117int mailmbox_validate_write_lock(struct mailmbox_folder * folder);
118
119int mailmbox_validate_read_lock(struct mailmbox_folder * folder);
120
121
122/* fetch message */
123
124int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder,
125 uint32_t num, char ** result,
126 size_t * result_len);
127
128int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder,
129 uint32_t num, char ** result,
130 size_t * result_len);
131
132/* append message */
133
134int
135mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder,
136 carray * append_tab);
137
138int mailmbox_expunge_no_lock(struct mailmbox_folder * folder);
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/include/libetpan/mailmbox_types.h b/libetpan/include/libetpan/mailmbox_types.h
new file mode 100644
index 0000000..4ce241d
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmbox_types.h
@@ -0,0 +1,143 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMBOX_TYPES_H
37
38#define MAILMBOX_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45
46#include <libetpan/libetpan-config.h>
47
48#include <libetpan/mailimf.h>
49#include <libetpan/carray.h>
50#include <libetpan/chash.h>
51
52enum {
53 MAILMBOX_NO_ERROR = 0,
54 MAILMBOX_ERROR_PARSE,
55 MAILMBOX_ERROR_INVAL,
56 MAILMBOX_ERROR_FILE_NOT_FOUND,
57 MAILMBOX_ERROR_MEMORY,
58 MAILMBOX_ERROR_TEMPORARY_FILE,
59 MAILMBOX_ERROR_FILE,
60 MAILMBOX_ERROR_MSG_NOT_FOUND,
61 MAILMBOX_ERROR_READONLY,
62};
63
64
65struct mailmbox_folder {
66 char mb_filename[PATH_MAX];
67
68 time_t mb_mtime;
69
70 int mb_fd;
71 int mb_read_only;
72 int mb_no_uid;
73
74 int mb_changed;
75 unsigned int mb_deleted_count;
76
77 char * mb_mapping;
78 size_t mb_mapping_size;
79
80 uint32_t mb_written_uid;
81 uint32_t mb_max_uid;
82
83 chash * mb_hash;
84 carray * mb_tab;
85};
86
87struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename);
88void mailmbox_folder_free(struct mailmbox_folder * folder);
89
90
91struct mailmbox_msg_info {
92 unsigned int msg_index;
93 uint32_t msg_uid;
94 int msg_written_uid;
95 int msg_deleted;
96
97 size_t msg_start;
98 size_t msg_start_len;
99
100 size_t msg_headers;
101 size_t msg_headers_len;
102
103 size_t msg_body;
104 size_t msg_body_len;
105
106 size_t msg_size;
107
108 size_t msg_padding;
109};
110
111
112int mailmbox_msg_info_update(struct mailmbox_folder * folder,
113 size_t msg_start, size_t msg_start_len,
114 size_t msg_headers, size_t msg_headers_len,
115 size_t msg_body, size_t msg_body_len,
116 size_t msg_size, size_t msg_padding,
117 uint32_t msg_uid);
118
119struct mailmbox_msg_info *
120mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
121 size_t msg_headers, size_t msg_headers_len,
122 size_t msg_body, size_t msg_body_len,
123 size_t msg_size, size_t msg_padding,
124 uint32_t msg_uid);
125
126void mailmbox_msg_info_free(struct mailmbox_msg_info * info);
127
128struct mailmbox_append_info {
129 const char * ai_message;
130 size_t ai_size;
131 unsigned int ai_uid;
132};
133
134struct mailmbox_append_info *
135mailmbox_append_info_new(const char * ai_message, size_t ai_size);
136
137void mailmbox_append_info_free(struct mailmbox_append_info * info);
138
139#ifdef __cplusplus
140}
141#endif
142
143#endif
diff --git a/libetpan/include/libetpan/mailmessage.h b/libetpan/include/libetpan/mailmessage.h
new file mode 100644
index 0000000..02b351b
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmessage.h
@@ -0,0 +1,379 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef MAILMESSAGE_H
39
40#define MAILMESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mailmessage_new
48
49 This function will initializes a new empty message.
50
51 @return a new empty message will be returned.
52*/
53
54mailmessage * mailmessage_new(void);
55
56/*
57 mailmessage_free
58
59 This function will release the memory used by this message.
60*/
61
62void mailmessage_free(mailmessage * info);
63
64/*
65 mailmessage_init
66
67 This function will initializes a mailmessage structure
68 with a message from a given session.
69
70 @param msg_info This is the message to initialize.
71
72 @param session This is the source session of the message. It
73 can be NULL if the message does not get the information
74 through the session.
75
76 @param driver This is the driver to use for the message.
77
78 @param index This is the message number in the session. 0 can
79 be given if the message is not attached to a session.
80
81 @param size is an optional parameter, 0 can be given.
82 This is informational. This is the size of message content.
83
84 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
85 on error
86*/
87
88int mailmessage_init(mailmessage * msg_info,
89 mailsession * session,
90 mailmessage_driver * driver,
91 uint32_t index, size_t size);
92
93/*
94 mailmessage_flush
95
96 This function will release all the temporary resources that are not
97 necessary to use the mailmessage structure from memory. These
98 resources are for example cached information, such as the MIME
99 structure.
100
101 @param info is the message to clean.
102
103 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
104 on error. We can assume that MAIL_NO_ERROR is always returned.
105*/
106
107int mailmessage_flush(mailmessage * info);
108
109/*
110 mailmessage_check
111
112 This function will notify the new value of the flags to the session,
113 it must be called before mailsession_check_folder() in case the flags have
114 been changed.
115
116 @param info is the message to checkpoint.
117
118 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
119 on error. We can assume that MAIL_NO_ERROR is always returned.
120*/
121
122int mailmessage_check(mailmessage * info);
123
124/*
125 mailmessage_fetch_result_free
126
127 This function releases the memory used by a message returned
128 by any of the fetch function that returns a (char *).
129
130 @param msg_info is the message which the given buffer is from.
131
132 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
133 on error. We can assume that MAIL_NO_ERROR is always returned.
134*/
135
136int mailmessage_fetch_result_free(mailmessage * msg_info,
137 char * msg);
138
139/*
140 mailmessage_fetch
141
142 This function returns the content of the message (headers and text).
143
144 @param msg_info is the message from which we want to fetch information.
145
146 @param result The content of the message is returned in (* result)
147
148 @param result_len The length of the returned string is stored
149 in (* result_len).
150
151 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
152 on error.
153*/
154
155int mailmessage_fetch(mailmessage * msg_info,
156 char ** result,
157 size_t * result_len);
158
159/*
160 mailmessage_fetch_header
161
162 This function returns the header of the message as a string.
163
164 @param msg_info is the message from which we want to fetch information.
165
166 @param result The header of the message is returned in (* result)
167
168 @param result_len The length of the returned string is stored
169 in (* result_len).
170
171 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
172 on error.
173*/
174
175int mailmessage_fetch_header(mailmessage * msg_info,
176 char ** result,
177 size_t * result_len);
178
179/*
180 mailmessage_fetch_body
181
182 This function returns the content of the message (without headers).
183
184 @param msg_info is the message from which we want to fetch information.
185 @param result The message text (without headers) is returned
186 in (* result)
187 @param result_len The length of the returned string is stored
188 in (* result_len).
189
190 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
191 on error.
192*/
193
194int mailmessage_fetch_body(mailmessage * msg_info,
195 char ** result, size_t * result_len);
196
197/*
198 mailmessage_fetch_size
199
200 This function returns the size of the message content.
201
202 @param msg_info is the message from which we want to fetch information.
203
204 @param result The length of the message content is stored in (* result).
205
206 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
207 on error.
208*/
209
210int mailmessage_fetch_size(mailmessage * msg_info,
211 size_t * result);
212
213/*
214 mailmessage_get_bodystructure
215
216 This functions returns the MIME structure of the message.
217 The returned information MUST not be freed by hand. It is freed by
218 mailmessage_flush() or mailmessage_free().
219
220 @param msg_info is the message from which we want to fetch information.
221
222 @param result The MIME structure is stored in (* result).
223
224 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
225 on error.
226*/
227
228int mailmessage_get_bodystructure(mailmessage * msg_info,
229 struct mailmime ** result);
230
231/*
232 mailmessage_fetch_section
233
234 This function returns the content of a MIME part.
235
236 @param msg_info is the message from which we want to fetch information.
237
238 @param mime is the MIME part identifier.
239
240 @param result The content is returned in (* result)
241
242 @param result_len The length of the returned string is stored
243 in (* result_len).
244
245 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
246 on error.
247 */
248
249int mailmessage_fetch_section(mailmessage * msg_info,
250 struct mailmime * mime,
251 char ** result, size_t * result_len);
252
253/*
254 mailmessage_fetch_section_header
255
256 This function returns the header of the message contained
257 in the given MIME part.
258
259 @param msg_info is the message from which we want to fetch information.
260
261 @param mime is the MIME part identifier.
262
263 @param result The header is returned in (* result)
264
265 @param result_len The length of the returned string is stored
266 in (* result_len).
267
268 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
269 on error.
270*/
271
272int mailmessage_fetch_section_header(mailmessage * msg_info,
273 struct mailmime * mime,
274 char ** result,
275 size_t * result_len);
276
277/*
278 mailmessage_fetch_section_mime
279
280 This function returns the MIME header of the given MIME part.
281
282 @param msg_info is the message from which we want to fetch information.
283
284 @param mime is the MIME part identifier.
285
286 @param result The MIME header is returned in (* result)
287
288 @param result_len The length of the returned string is stored
289 in (* result_len).
290
291 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
292 on error.
293*/
294
295int mailmessage_fetch_section_mime(mailmessage * msg_info,
296 struct mailmime * mime,
297 char ** result,
298 size_t * result_len);
299
300/*
301 mailmessage_fetch_section_body
302
303 This function returns the text part of the message contained
304 in the given MIME part.
305
306 @param msg_info is the message from which we want to fetch information.
307
308 @param mime is the MIME part identifier.
309
310 @param result The message text is returned in (* result)
311
312 @param result_len The length of the returned string is stored
313 in (* result_len).
314
315 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
316 on error.
317 */
318
319int mailmessage_fetch_section_body(mailmessage * msg_info,
320 struct mailmime * mime,
321 char ** result,
322 size_t * result_len);
323
324/*
325 mailmessage_fetch_envelope
326
327 This function returns a list of parsed fields of the message,
328 chosen by the driver.
329 The returned structure must be freed with mailimf_fields_free().
330
331 @param msg_info is the message from which we want to fetch information.
332
333 @param result The headers list is returned in (* result)
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error.
337 */
338
339int mailmessage_fetch_envelope(mailmessage * msg_info,
340 struct mailimf_fields ** result);
341
342
343/*
344 mailmessage_get_flags
345
346 This function returns the flags related to the message.
347 The returned information MUST not be freed by hand. It is freed by
348 mailmessage_free().
349
350 @param msg_info is the message from which we want to fetch information.
351
352 @param result The flags are stored in (* result).
353
354 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
355 on error.
356*/
357
358int mailmessage_get_flags(mailmessage * msg_info,
359 struct mail_flags ** result);
360
361/*
362 mailmessage_resolve_single_fields
363
364 This function will use the fields information to fill the single_fields
365 structure in the mailmessage structure.
366
367 @param msg_info This is the msg_info to process.
368
369 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
370 on error.
371*/
372
373void mailmessage_resolve_single_fields(mailmessage * msg_info);
374
375#ifdef __cplusplus
376}
377#endif
378
379#endif
diff --git a/libetpan/include/libetpan/mailmessage_types.h b/libetpan/include/libetpan/mailmessage_types.h
new file mode 100644
index 0000000..c3ed2c4
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmessage_types.h
@@ -0,0 +1,50 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMESSAGE_TYPES_H
37
38#define MAILMESSAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#ifdef __cplusplus
47}
48#endif
49
50#endif
diff --git a/libetpan/include/libetpan/mailmh.h b/libetpan/include/libetpan/mailmh.h
new file mode 100644
index 0000000..dc1861b
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmh.h
@@ -0,0 +1,152 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMH_H
37
38#define MAILMH_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46#include <libetpan/carray.h>
47#if 0
48#include <libetpan/cinthash.h>
49#endif
50#include <libetpan/chash.h>
51
52enum {
53 MAILMH_NO_ERROR = 0,
54 MAILMH_ERROR_FOLDER,
55 MAILMH_ERROR_MEMORY,
56 MAILMH_ERROR_FILE,
57 MAILMH_ERROR_COULD_NOT_ALLOC_MSG,
58 MAILMH_ERROR_RENAME,
59 MAILMH_ERROR_MSG_NOT_FOUND,
60};
61
62struct mailmh {
63 struct mailmh_folder * mh_main;
64};
65
66struct mailmh_msg_info {
67 unsigned int msg_array_index;
68 uint32_t msg_index;
69 size_t msg_size;
70 time_t msg_mtime;
71};
72
73struct mailmh_folder {
74 char * fl_filename;
75 unsigned int fl_array_index;
76
77 char * fl_name;
78 time_t fl_mtime;
79 struct mailmh_folder * fl_parent;
80 uint32_t fl_max_index;
81
82 carray * fl_msgs_tab;
83#if 0
84 cinthash_t * fl_msgs_hash;
85#endif
86 chash * fl_msgs_hash;
87
88 carray * fl_subfolders_tab;
89 chash * fl_subfolders_hash;
90};
91
92struct mailmh * mailmh_new(const char * foldername);
93void mailmh_free(struct mailmh * f);
94
95struct mailmh_msg_info *
96mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime);
97void mailmh_msg_info_free(struct mailmh_msg_info * msg_info);
98
99struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent,
100 const char * name);
101void mailmh_folder_free(struct mailmh_folder * folder);
102
103int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
104 const char * name);
105
106struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root,
107 const char * filename);
108
109int mailmh_folder_remove_subfolder(struct mailmh_folder * folder);
110
111int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
112 struct mailmh_folder * dst_folder,
113 const char * new_name);
114
115int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
116 uint32_t index, char ** result);
117
118int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
119 uint32_t index, int flags, int * result);
120
121int mailmh_folder_get_message_size(struct mailmh_folder * folder,
122 uint32_t index, size_t * result);
123
124int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
125 const char * message, size_t size,
126 uint32_t * pindex);
127
128int mailmh_folder_add_message(struct mailmh_folder * folder,
129 const char * message, size_t size);
130
131int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
132 int fd, uint32_t * pindex);
133
134int mailmh_folder_add_message_file(struct mailmh_folder * folder,
135 int fd);
136
137int mailmh_folder_remove_message(struct mailmh_folder * folder,
138 uint32_t index);
139
140int mailmh_folder_move_message(struct mailmh_folder * dest_folder,
141 struct mailmh_folder * src_folder,
142 uint32_t index);
143
144int mailmh_folder_update(struct mailmh_folder * folder);
145
146unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder);
147
148#ifdef __cplusplus
149}
150#endif
151
152#endif
diff --git a/libetpan/include/libetpan/mailmime.h b/libetpan/include/libetpan/mailmime.h
new file mode 100644
index 0000000..83cba25
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_H
37
38#define MAILMIME_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf.h>
45#include <libetpan/mailmime_types.h>
46#include <libetpan/mailmime_types_helper.h>
47#include <libetpan/mailmime_content.h>
48#include <libetpan/mailmime_decode.h>
49#include <libetpan/mailmime_disposition.h>
50#include <libetpan/mailmime_write_file.h>
51#include <libetpan/mailmime_write_mem.h>
52#include <libetpan/mailmime_write_generic.h>
53
54int mailmime_content_parse(const char * message, size_t length,
55 size_t * index,
56 struct mailmime_content ** result);
57
58int mailmime_description_parse(const char * message, size_t length,
59 size_t * index,
60 char ** result);
61
62int mailmime_encoding_parse(const char * message, size_t length,
63 size_t * index,
64 struct mailmime_mechanism ** result);
65
66int
67mailmime_field_parse(struct mailimf_optional_field * field,
68 struct mailmime_field ** result);
69
70int mailmime_id_parse(const char * message, size_t length,
71 size_t * index, char ** result);
72
73int
74mailmime_fields_parse(struct mailimf_fields *
75 fields,
76 struct mailmime_fields **
77 result);
78
79int mailmime_version_parse(const char * message, size_t length,
80 size_t * index,
81 uint32_t * result);
82
83int
84mailmime_extension_token_parse(const char * message, size_t length,
85 size_t * index, char ** result);
86
87int mailmime_parameter_parse(const char * message, size_t length,
88 size_t * index,
89 struct mailmime_parameter ** result);
90
91int mailmime_value_parse(const char * message, size_t length,
92 size_t * index, char ** result);
93
94int mailmime_language_parse(const char * message, size_t length,
95 size_t * index,
96 struct mailmime_language ** result);
97
98#ifdef __cplusplus
99}
100#endif
101
102#endif
diff --git a/libetpan/include/libetpan/mailmime_content.h b/libetpan/include/libetpan/mailmime_content.h
new file mode 100644
index 0000000..989e515
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_content.h
@@ -0,0 +1,89 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_CONTENT_H
37
38#define MAILMIME_CONTENT_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46char * mailmime_content_charset_get(struct mailmime_content * content);
47
48char * mailmime_content_param_get(struct mailmime_content * content,
49 char * name);
50
51int mailmime_parse(const char * message, size_t length,
52 size_t * index, struct mailmime ** result);
53
54int mailmime_get_section(struct mailmime * mime,
55 struct mailmime_section * section,
56 struct mailmime ** result);
57
58
59char * mailmime_extract_boundary(struct mailmime_content * content_type);
60
61
62/* decode */
63
64int mailmime_base64_body_parse(const char * message, size_t length,
65 size_t * index, char ** result,
66 size_t * result_len);
67
68int mailmime_quoted_printable_body_parse(const char * message, size_t length,
69 size_t * index, char ** result,
70 size_t * result_len, int in_header);
71
72
73int mailmime_binary_body_parse(const char * message, size_t length,
74 size_t * index, char ** result,
75 size_t * result_len);
76
77int mailmime_part_parse(const char * message, size_t length,
78 size_t * index,
79 int encoding, char ** result, size_t * result_len);
80
81
82int mailmime_get_section_id(struct mailmime * mime,
83 struct mailmime_section ** result);
84
85#ifdef __cplusplus
86}
87#endif
88
89#endif
diff --git a/libetpan/include/libetpan/mailmime_decode.h b/libetpan/include/libetpan/mailmime_decode.h
new file mode 100644
index 0000000..7b9d693
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_decode.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_DECODE_H
37
38#define MAILMIME_DECODE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_encoded_phrase_parse(const char * default_fromcode,
47 const char * message, size_t length,
48 size_t * index, const char * tocode,
49 char ** result);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/include/libetpan/mailmime_disposition.h b/libetpan/include/libetpan/mailmime_disposition.h
new file mode 100644
index 0000000..e992d7c
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_disposition.h
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_DISPOSITION_H
37
38#define MAILMIME_DISPOSITION_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_disposition_parse(const char * message, size_t length,
47 size_t * index,
48 struct mailmime_disposition ** result);
49
50int
51mailmime_disposition_type_parse(const char * message, size_t length,
52 size_t * index,
53 struct mailmime_disposition_type ** result);
54
55int mailmime_disposition_guess_type(const char * message, size_t length,
56 size_t index);
57
58#ifdef __cplusplus
59}
60#endif
61
62#endif
diff --git a/libetpan/include/libetpan/mailmime_types.h b/libetpan/include/libetpan/mailmime_types.h
new file mode 100644
index 0000000..21f0d96
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_types.h
@@ -0,0 +1,440 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_TYPES_H
37
38#define MAILMIME_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <libetpan/mailimf.h>
46#include <libetpan/clist.h>
47
48enum {
49 MAILMIME_COMPOSITE_TYPE_ERROR,
50 MAILMIME_COMPOSITE_TYPE_MESSAGE,
51 MAILMIME_COMPOSITE_TYPE_MULTIPART,
52 MAILMIME_COMPOSITE_TYPE_EXTENSION
53};
54
55struct mailmime_composite_type {
56 int ct_type;
57 char * ct_token;
58};
59
60
61struct mailmime_content {
62 struct mailmime_type * ct_type;
63 char * ct_subtype;
64 clist * ct_parameters; /* elements are (struct mailmime_parameter *) */
65};
66
67
68enum {
69 MAILMIME_DISCRETE_TYPE_ERROR,
70 MAILMIME_DISCRETE_TYPE_TEXT,
71 MAILMIME_DISCRETE_TYPE_IMAGE,
72 MAILMIME_DISCRETE_TYPE_AUDIO,
73 MAILMIME_DISCRETE_TYPE_VIDEO,
74 MAILMIME_DISCRETE_TYPE_APPLICATION,
75 MAILMIME_DISCRETE_TYPE_EXTENSION
76};
77
78struct mailmime_discrete_type {
79 int dt_type;
80 char * dt_extension;
81};
82
83enum {
84 MAILMIME_FIELD_NONE,
85 MAILMIME_FIELD_TYPE,
86 MAILMIME_FIELD_TRANSFER_ENCODING,
87 MAILMIME_FIELD_ID,
88 MAILMIME_FIELD_DESCRIPTION,
89 MAILMIME_FIELD_VERSION,
90 MAILMIME_FIELD_DISPOSITION,
91 MAILMIME_FIELD_LANGUAGE,
92};
93
94struct mailmime_field {
95 int fld_type;
96 union {
97 struct mailmime_content * fld_content;
98 struct mailmime_mechanism * fld_encoding;
99 char * fld_id;
100 char * fld_description;
101 uint32_t fld_version;
102 struct mailmime_disposition * fld_disposition;
103 struct mailmime_language * fld_language;
104 } fld_data;
105};
106
107enum {
108 MAILMIME_MECHANISM_ERROR,
109 MAILMIME_MECHANISM_7BIT,
110 MAILMIME_MECHANISM_8BIT,
111 MAILMIME_MECHANISM_BINARY,
112 MAILMIME_MECHANISM_QUOTED_PRINTABLE,
113 MAILMIME_MECHANISM_BASE64,
114 MAILMIME_MECHANISM_TOKEN
115};
116
117struct mailmime_mechanism {
118 int enc_type;
119 char * enc_token;
120};
121
122
123struct mailmime_fields {
124 clist * fld_list; /* list of (struct mailmime_field *) */
125};
126
127
128struct mailmime_parameter {
129 char * pa_name;
130 char * pa_value;
131};
132
133enum {
134 MAILMIME_TYPE_ERROR,
135 MAILMIME_TYPE_DISCRETE_TYPE,
136 MAILMIME_TYPE_COMPOSITE_TYPE
137};
138
139struct mailmime_type {
140 int tp_type;
141 union {
142 struct mailmime_discrete_type * tp_discrete_type;
143 struct mailmime_composite_type * tp_composite_type;
144 } tp_data;
145};
146
147void mailmime_attribute_free(char * attribute);
148
149struct mailmime_composite_type *
150mailmime_composite_type_new(int ct_type, char * ct_token);
151
152void mailmime_composite_type_free(struct mailmime_composite_type * ct);
153
154struct mailmime_content *
155mailmime_content_new(struct mailmime_type * ct_type,
156 char * ct_subtype,
157 clist * ct_parameters);
158
159void mailmime_content_free(struct mailmime_content * content);
160
161void mailmime_description_free(char * description);
162
163struct mailmime_discrete_type *
164mailmime_discrete_type_new(int dt_type, char * dt_extension);
165
166void mailmime_discrete_type_free(struct mailmime_discrete_type *
167 discrete_type);
168
169void mailmime_encoding_free(struct mailmime_mechanism * encoding);
170
171void mailmime_extension_token_free(char * extension);
172
173void mailmime_id_free(char * id);
174
175struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token);
176
177void mailmime_mechanism_free(struct mailmime_mechanism * mechanism);
178
179struct mailmime_parameter *
180mailmime_parameter_new(char * pa_name, char * pa_value);
181
182void mailmime_parameter_free(struct mailmime_parameter * parameter);
183
184void mailmime_subtype_free(char * subtype);
185
186void mailmime_token_free(char * token);
187
188struct mailmime_type *
189mailmime_type_new(int tp_type,
190 struct mailmime_discrete_type * tp_discrete_type,
191 struct mailmime_composite_type * tp_composite_type);
192
193void mailmime_type_free(struct mailmime_type * type);
194
195void mailmime_value_free(char * value);
196
197
198
199struct mailmime_language {
200 clist * lg_list; /* atom (char *) */
201};
202
203struct mailmime_language * mailmime_language_new(clist * lg_list);
204
205void mailmime_language_free(struct mailmime_language * lang);
206
207
208/*
209void mailmime_x_token_free(gchar * x_token);
210*/
211
212struct mailmime_field *
213mailmime_field_new(int fld_type,
214 struct mailmime_content * fld_content,
215 struct mailmime_mechanism * fld_encoding,
216 char * fld_id,
217 char * fld_description,
218 uint32_t fld_version,
219 struct mailmime_disposition * fld_disposition,
220 struct mailmime_language * fld_language);
221
222void mailmime_field_free(struct mailmime_field * field);
223
224struct mailmime_fields * mailmime_fields_new(clist * fld_list);
225
226void mailmime_fields_free(struct mailmime_fields * fields);
227
228
229struct mailmime_multipart_body {
230 clist * bd_list;
231};
232
233struct mailmime_multipart_body *
234mailmime_multipart_body_new(clist * bd_list);
235
236void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body);
237
238
239enum {
240 MAILMIME_DATA_TEXT,
241 MAILMIME_DATA_FILE,
242};
243
244struct mailmime_data {
245 int dt_type;
246 int dt_encoding;
247 int dt_encoded;
248 union {
249 struct {
250 const char * dt_data;
251 size_t dt_length;
252 } dt_text;
253 char * dt_filename;
254 } dt_data;
255};
256
257struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding,
258 int dt_encoded, const char * dt_data, size_t dt_length,
259 char * dt_filename);
260
261void mailmime_data_free(struct mailmime_data * mime_data);
262
263
264enum {
265 MAILMIME_NONE,
266 MAILMIME_SINGLE,
267 MAILMIME_MULTIPLE,
268 MAILMIME_MESSAGE,
269};
270
271struct mailmime {
272 /* parent information */
273 int mm_parent_type;
274 struct mailmime * mm_parent;
275 clistiter * mm_multipart_pos;
276
277 int mm_type;
278 const char * mm_mime_start;
279 size_t mm_length;
280
281 struct mailmime_fields * mm_mime_fields;
282 struct mailmime_content * mm_content_type;
283
284 struct mailmime_data * mm_body;
285 union {
286 /* single part */
287 struct mailmime_data * mm_single; /* XXX - was body */
288
289 /* multi-part */
290 struct {
291 struct mailmime_data * mm_preamble;
292 struct mailmime_data * mm_epilogue;
293 clist * mm_mp_list;
294 } mm_multipart;
295
296 /* message */
297 struct {
298 struct mailimf_fields * mm_fields;
299 struct mailmime * mm_msg_mime;
300 } mm_message;
301
302 } mm_data;
303};
304
305struct mailmime * mailmime_new(int mm_type,
306 const char * mm_mime_start, size_t mm_length,
307 struct mailmime_fields * mm_mime_fields,
308 struct mailmime_content * mm_content_type,
309 struct mailmime_data * mm_body,
310 struct mailmime_data * mm_preamble,
311 struct mailmime_data * mm_epilogue,
312 clist * mm_mp_list,
313 struct mailimf_fields * mm_fields,
314 struct mailmime * mm_msg_mime);
315
316void mailmime_free(struct mailmime * mime);
317
318struct mailmime_encoded_word {
319 char * wd_charset;
320 char * wd_text;
321};
322
323struct mailmime_encoded_word *
324mailmime_encoded_word_new(char * wd_charset, char * wd_text);
325
326void mailmime_encoded_word_free(struct mailmime_encoded_word * ew);
327
328void mailmime_charset_free(char * charset);
329
330void mailmime_encoded_text_free(char * text);
331
332
333struct mailmime_disposition {
334 struct mailmime_disposition_type * dsp_type;
335 clist * dsp_parms; /* struct mailmime_disposition_parm */
336};
337
338
339enum {
340 MAILMIME_DISPOSITION_TYPE_ERROR,
341 MAILMIME_DISPOSITION_TYPE_INLINE,
342 MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
343 MAILMIME_DISPOSITION_TYPE_EXTENSION
344};
345
346struct mailmime_disposition_type {
347 int dsp_type;
348 char * dsp_extension;
349};
350
351
352enum {
353 MAILMIME_DISPOSITION_PARM_FILENAME,
354 MAILMIME_DISPOSITION_PARM_CREATION_DATE,
355 MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE,
356 MAILMIME_DISPOSITION_PARM_READ_DATE,
357 MAILMIME_DISPOSITION_PARM_SIZE,
358 MAILMIME_DISPOSITION_PARM_PARAMETER
359};
360
361struct mailmime_disposition_parm {
362 int pa_type;
363 union {
364 char * pa_filename;
365 char * pa_creation_date;
366 char * pa_modification_date;
367 char * pa_read_date;
368 size_t pa_size;
369 struct mailmime_parameter * pa_parameter;
370 } pa_data;
371};
372
373struct mailmime_disposition *
374mailmime_disposition_new(struct mailmime_disposition_type * dsp_type,
375 clist * dsp_parms);
376
377void mailmime_disposition_free(struct mailmime_disposition * dsp);
378
379struct mailmime_disposition_type *
380mailmime_disposition_type_new(int dt_type, char * dt_extension);
381
382void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type);
383
384struct mailmime_disposition_parm *
385mailmime_disposition_parm_new(int pa_type,
386 char * pa_filename,
387 char * pa_creation_date,
388 char * pa_modification_date,
389 char * pa_read_date,
390 size_t pa_size,
391 struct mailmime_parameter * pa_parameter);
392
393void mailmime_disposition_parm_free(struct mailmime_disposition_parm *
394 dsp_parm);
395
396void mailmime_filename_parm_free(char * filename);
397
398void mailmime_creation_date_parm_free(char * date);
399
400void mailmime_modification_date_parm_free(char * date);
401
402void mailmime_read_date_parm_free(char * date);
403
404void mailmime_quoted_date_time_free(char * date);
405
406struct mailmime_section {
407 clist * sec_list; /* list of (uint32 *) */
408};
409
410struct mailmime_section * mailmime_section_new(clist * list);
411
412void mailmime_section_free(struct mailmime_section * section);
413
414
415void mailmime_decoded_part_free(char * part);
416
417struct mailmime_single_fields {
418 struct mailmime_content * fld_content;
419 char * fld_content_charset;
420 char * fld_content_boundary;
421 char * fld_content_name;
422 struct mailmime_mechanism * fld_encoding;
423 char * fld_id;
424 char * fld_description;
425 uint32_t fld_version;
426 struct mailmime_disposition * fld_disposition;
427 char * fld_disposition_filename;
428 char * fld_disposition_creation_date;
429 char * fld_disposition_modification_date;
430 char * fld_disposition_read_date;
431 size_t fld_disposition_size;
432 struct mailmime_language * fld_language;
433};
434
435#ifdef __cplusplus
436}
437#endif
438
439#endif
440
diff --git a/libetpan/include/libetpan/mailmime_types_helper.h b/libetpan/include/libetpan/mailmime_types_helper.h
new file mode 100644
index 0000000..cdbbff9
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_types_helper.h
@@ -0,0 +1,165 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_TYPES_HELPER_H
37
38#define MAILMIME_TYPES_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_transfer_encoding_get(struct mailmime_fields * fields);
47
48struct mailmime_disposition *
49mailmime_disposition_new_filename(int type, char * filename);
50
51struct mailmime_fields * mailmime_fields_new_empty(void);
52
53int mailmime_fields_add(struct mailmime_fields * fields,
54 struct mailmime_field * field);
55
56struct mailmime_fields *
57mailmime_fields_new_with_data(struct mailmime_mechanism * encoding,
58 char * id,
59 char * description,
60 struct mailmime_disposition * disposition,
61 struct mailmime_language * language);
62
63struct mailmime_fields *
64mailmime_fields_new_with_version(struct mailmime_mechanism * encoding,
65 char * id,
66 char * description,
67 struct mailmime_disposition * disposition,
68 struct mailmime_language * language);
69
70struct mailmime_content * mailmime_get_content_message(void);
71struct mailmime_content * mailmime_get_content_text(void);
72/* struct mailmime_content * mailmime_get_content(char * mime_type); */
73
74#define mailmime_get_content mailmime_content_new_with_str
75
76struct mailmime_data *
77mailmime_data_new_data(int encoding, int encoded,
78 const char * data, size_t length);
79
80struct mailmime_data *
81mailmime_data_new_file(int encoding, int encoded,
82 char * filename);
83
84#if 0
85struct mailmime *
86mailmime_new_message_file(char * filename);
87
88struct mailmime *
89mailmime_new_message_text(char * data_str, size_t length);
90#endif
91
92struct mailmime *
93mailmime_new_message_data(struct mailmime * msg_mime);
94
95struct mailmime *
96mailmime_new_empty(struct mailmime_content * content,
97 struct mailmime_fields * mime_fields);
98
99int
100mailmime_new_with_content(const char * content_type,
101 struct mailmime_fields * mime_fields,
102 struct mailmime ** result);
103
104int mailmime_set_preamble_file(struct mailmime * build_info,
105 char * filename);
106
107int mailmime_set_epilogue_file(struct mailmime * build_info,
108 char * filename);
109
110int mailmime_set_preamble_text(struct mailmime * build_info,
111 char * data_str, size_t length);
112
113int mailmime_set_epilogue_text(struct mailmime * build_info,
114 char * data_str, size_t length);
115
116int mailmime_set_body_file(struct mailmime * build_info,
117 char * filename);
118
119int mailmime_set_body_text(struct mailmime * build_info,
120 char * data_str, size_t length);
121
122int mailmime_add_part(struct mailmime * build_info,
123 struct mailmime * part);
124
125void mailmime_remove_part(struct mailmime * mime);
126
127void mailmime_set_imf_fields(struct mailmime * build_info,
128 struct mailimf_fields * fields);
129
130
131struct mailmime_disposition *
132mailmime_disposition_new_with_data(int type,
133 char * filename, char * creation_date, char * modification_date,
134 char * read_date, size_t size);
135
136void mailmime_single_fields_init(struct mailmime_single_fields * single_fields,
137 struct mailmime_fields * fld_fields,
138 struct mailmime_content * fld_content);
139
140struct mailmime_single_fields *
141mailmime_single_fields_new(struct mailmime_fields * fld_fields,
142 struct mailmime_content * fld_content);
143
144void mailmime_single_fields_free(struct mailmime_single_fields *
145 single_fields);
146
147int mailmime_smart_add_part(struct mailmime * mime,
148 struct mailmime * mime_sub);
149
150int mailmime_smart_remove_part(struct mailmime * mime);
151
152struct mailmime_content * mailmime_content_new_with_str(const char * str);
153
154struct mailmime_fields * mailmime_fields_new_encoding(int type);
155
156struct mailmime * mailmime_multiple_new(const char * type);
157
158struct mailmime_fields * mailmime_fields_new_filename(int dsp_type,
159 char * filename, int encoding_type);
160
161#ifdef __cplusplus
162}
163#endif
164
165#endif
diff --git a/libetpan/include/libetpan/mailmime_write_file.h b/libetpan/include/libetpan/mailmime_write_file.h
new file mode 100644
index 0000000..4cfa484
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_write_file.h
@@ -0,0 +1,105 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_FILE_H
37
38#define MAILMIME_WRITE_FILE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47 //#define MAILMIME_WRITE_COMPATIBILITY
48
49
50int mailmime_fields_write_file(FILE * f, int * col,
51 struct mailmime_fields * fields);
52
53int mailmime_content_write_file(FILE * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_content_type_write_file(FILE * f, int * col,
57 struct mailmime_content * content);
58
59int mailmime_write_file(FILE * f, int * col,
60 struct mailmime * build_info);
61
62int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext,
63 const char * text, size_t size);
64
65int mailmime_base64_write_file(FILE * f, int * col,
66 const char * text, size_t size);
67
68int mailmime_data_write_file(FILE * f, int * col,
69 struct mailmime_data * data,
70 int istext);
71
72
73/* binary compatibility with 0.34 - begin */
74
75#ifdef MAILMIME_WRITE_COMPATIBILITY
76int mailmime_fields_write(FILE * f, int * col,
77 struct mailmime_fields * fields);
78
79int mailmime_content_write(FILE * f, int * col,
80 struct mailmime_content * content);
81
82int mailmime_content_type_write(FILE * f, int * col,
83 struct mailmime_content * content);
84
85int mailmime_write(FILE * f, int * col,
86 struct mailmime * build_info);
87
88int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
89 const char * text, size_t size);
90
91int mailmime_base64_write(FILE * f, int * col,
92 const char * text, size_t size);
93
94int mailmime_data_write(FILE * f, int * col,
95 struct mailmime_data * data,
96 int istext);
97#endif
98
99/* binary compatibility with 0.34 - end */
100
101#ifdef __cplusplus
102}
103#endif
104
105#endif
diff --git a/libetpan/include/libetpan/mailmime_write_generic.h b/libetpan/include/libetpan/mailmime_write_generic.h
new file mode 100644
index 0000000..0d9a725
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_write_generic.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_GENERIC_H
37
38#define MAILMIME_WRITE_GENERIC_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailmime_data * mime_data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/include/libetpan/mailmime_write_mem.h b/libetpan/include/libetpan/mailmime_write_mem.h
new file mode 100644
index 0000000..f86d129
--- a/dev/null
+++ b/libetpan/include/libetpan/mailmime_write_mem.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_MEM_H
37
38#define MAILMIME_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <libetpan/mmapstring.h>
46
47int mailmime_fields_write_mem(MMAPString * f, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_mem(MMAPString * f, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_mem(MMAPString * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_mem(MMAPString * f, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_mem(MMAPString * f, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_mem(MMAPString * f, int * col,
66 struct mailmime_data * data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/include/libetpan/mailpop3.h b/libetpan/include/libetpan/mailpop3.h
new file mode 100644
index 0000000..62275f8
--- a/dev/null
+++ b/libetpan/include/libetpan/mailpop3.h
@@ -0,0 +1,101 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_H
37
38#define MAILPOP3_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailpop3_types.h>
45
46#include <libetpan/mailpop3_helper.h>
47
48#include <libetpan/mailpop3_socket.h>
49#include <libetpan/mailpop3_ssl.h>
50
51#define POP3_STRING_SIZE 513
52
53mailpop3 * mailpop3_new(size_t pop3_progr_rate,
54 progress_function * pop3_progr_fun);
55
56void mailpop3_free(mailpop3 * f);
57
58int mailpop3_connect(mailpop3 * f, mailstream * s);
59
60int mailpop3_quit(mailpop3 * f);
61
62
63int mailpop3_apop(mailpop3 * f, const char * user, const char * password);
64
65int mailpop3_user(mailpop3 * f, const char * user);
66
67int mailpop3_pass(mailpop3 * f, const char * password);
68
69void mailpop3_list(mailpop3 * f, carray ** result);
70
71int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result,
72 size_t * result_len);
73
74int mailpop3_top(mailpop3 * f, unsigned int index,
75 unsigned int count, char ** result,
76 size_t * result_len);
77
78int mailpop3_dele(mailpop3 * f, unsigned int index);
79
80int mailpop3_noop(mailpop3 * f);
81
82int mailpop3_rset(mailpop3 * f);
83
84void mailpop3_top_free(char * str);
85
86void mailpop3_retr_free(char * str);
87
88int mailpop3_get_msg_info(mailpop3 * f, unsigned int index,
89 struct mailpop3_msg_info ** result);
90
91int mailpop3_capa(mailpop3 * f, clist ** result);
92
93void mailpop3_capa_resp_free(clist * capa_list);
94
95int mailpop3_stls(mailpop3 * f);
96
97#ifdef __cplusplus
98}
99#endif
100
101#endif
diff --git a/libetpan/include/libetpan/mailpop3_helper.h b/libetpan/include/libetpan/mailpop3_helper.h
new file mode 100644
index 0000000..cec93da
--- a/dev/null
+++ b/libetpan/include/libetpan/mailpop3_helper.h
@@ -0,0 +1,64 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_HELPER_H
37
38#define MAILPOP3_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailpop3.h"
45
46int mailpop3_login_apop(mailpop3 * f,
47 char * user,
48 char * password);
49
50int mailpop3_login(mailpop3 * f,
51 char * user,
52 char * password);
53
54int mailpop3_header(mailpop3 * f, uint32_t index, char ** result,
55 size_t * result_len);
56
57void mailpop3_header_free(char * str);
58
59#ifdef __cplusplus
60}
61#endif
62
63#endif
64
diff --git a/libetpan/include/libetpan/mailpop3_socket.h b/libetpan/include/libetpan/mailpop3_socket.h
new file mode 100644
index 0000000..262b2ab
--- a/dev/null
+++ b/libetpan/include/libetpan/mailpop3_socket.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_SOCKET_H
37
38#define MAILPOP3_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailpop3_types.h>
47
48int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/include/libetpan/mailpop3_ssl.h b/libetpan/include/libetpan/mailpop3_ssl.h
new file mode 100644
index 0000000..38e0769
--- a/dev/null
+++ b/libetpan/include/libetpan/mailpop3_ssl.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_SSL_H
37
38#define MAILPOP3_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailpop3_types.h>
47
48int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/include/libetpan/mailpop3_types.h b/libetpan/include/libetpan/mailpop3_types.h
new file mode 100644
index 0000000..18a68bc
--- a/dev/null
+++ b/libetpan/include/libetpan/mailpop3_types.h
@@ -0,0 +1,107 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_TYPES_H
37
38#define MAILPOP3_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailstream.h>
45#include <libetpan/mmapstring.h>
46#include <libetpan/carray.h>
47#include <libetpan/clist.h>
48
49#include <inttypes.h>
50
51enum {
52 MAILPOP3_NO_ERROR = 0,
53 MAILPOP3_ERROR_BAD_STATE,
54 MAILPOP3_ERROR_UNAUTHORIZED,
55 MAILPOP3_ERROR_STREAM,
56 MAILPOP3_ERROR_DENIED,
57 MAILPOP3_ERROR_BAD_USER,
58 MAILPOP3_ERROR_BAD_PASSWORD,
59 MAILPOP3_ERROR_CANT_LIST,
60 MAILPOP3_ERROR_NO_SUCH_MESSAGE,
61 MAILPOP3_ERROR_MEMORY,
62 MAILPOP3_ERROR_CONNECTION_REFUSED,
63 MAILPOP3_ERROR_APOP_NOT_SUPPORTED,
64 MAILPOP3_ERROR_CAPA_NOT_SUPPORTED,
65 MAILPOP3_ERROR_STLS_NOT_SUPPORTED,
66};
67
68struct mailpop3
69{
70 char * pop3_response; /* response message */
71 char * pop3_timestamp; /* connection timestamp */
72
73 /* internals */
74 mailstream * pop3_stream;
75 size_t pop3_progr_rate;
76 progress_function * pop3_progr_fun;
77
78 MMAPString * pop3_stream_buffer; /* buffer for lines reading */
79 MMAPString * pop3_response_buffer; /* buffer for responses */
80
81 carray * pop3_msg_tab; /* list of pop3_msg_info structures */
82 int pop3_state; /* state */
83
84 unsigned int pop3_deleted_count;
85};
86
87typedef struct mailpop3 mailpop3;
88
89struct mailpop3_msg_info
90{
91 unsigned int msg_index;
92 uint32_t msg_size;
93 char * msg_uidl;
94 int msg_deleted;
95};
96
97
98struct mailpop3_capa {
99 char * cap_name;
100 clist * cap_param; /* (char *) */
101};
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif
diff --git a/libetpan/include/libetpan/mailprivacy.h b/libetpan/include/libetpan/mailprivacy.h
new file mode 100644
index 0000000..1f77331
--- a/dev/null
+++ b/libetpan/include/libetpan/mailprivacy.h
@@ -0,0 +1,117 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPRIVACY_H
37
38#define MAILPRIVACY_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailprivacy_types.h>
42#include <libetpan/mailprivacy_tools.h>
43
44struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative);
45
46void mailprivacy_free(struct mailprivacy * privacy);
47
48int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy,
49 mailmessage * msg_info,
50 struct mailmime ** result);
51
52void mailprivacy_msg_flush(struct mailprivacy * privacy,
53 mailmessage * msg_info);
54
55int mailprivacy_msg_fetch_section(struct mailprivacy * privacy,
56 mailmessage * msg_info,
57 struct mailmime * mime,
58 char ** result, size_t * result_len);
59
60int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy,
61 mailmessage * msg_info,
62 struct mailmime * mime,
63 char ** result,
64 size_t * result_len);
65
66int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy,
67 mailmessage * msg_info,
68 struct mailmime * mime,
69 char ** result,
70 size_t * result_len);
71
72int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy,
73 mailmessage * msg_info,
74 struct mailmime * mime,
75 char ** result,
76 size_t * result_len);
77
78void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy,
79 mailmessage * msg_info,
80 char * msg);
81
82int mailprivacy_msg_fetch(struct mailprivacy * privacy,
83 mailmessage * msg_info,
84 char ** result,
85 size_t * result_len);
86
87int mailprivacy_msg_fetch_header(struct mailprivacy * privacy,
88 mailmessage * msg_info,
89 char ** result,
90 size_t * result_len);
91
92int mailprivacy_register(struct mailprivacy * privacy,
93 struct mailprivacy_protocol * protocol);
94
95void mailprivacy_unregister(struct mailprivacy * privacy,
96 struct mailprivacy_protocol * protocol);
97
98char * mailprivacy_get_encryption_name(struct mailprivacy * privacy,
99 char * privacy_driver, char * privacy_encryption);
100
101int mailprivacy_encrypt(struct mailprivacy * privacy,
102 char * privacy_driver, char * privacy_encryption,
103 struct mailmime * mime,
104 struct mailmime ** result);
105
106void mailprivacy_debug(struct mailprivacy * privacy, FILE * f);
107
108carray * mailprivacy_get_protocols(struct mailprivacy * privacy);
109
110int mailprivacy_is_encrypted(struct mailprivacy * privacy,
111 mailmessage * msg,
112 struct mailmime * mime);
113
114void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy,
115 struct mailmime * mime);
116
117#endif
diff --git a/libetpan/include/libetpan/mailprivacy_gnupg.h b/libetpan/include/libetpan/mailprivacy_gnupg.h
new file mode 100644
index 0000000..013c8a4
--- a/dev/null
+++ b/libetpan/include/libetpan/mailprivacy_gnupg.h
@@ -0,0 +1,46 @@
1/*
2 * etPan! -- a mail user agent
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_GNUPG_H
37
38#define MAIL_PRIVACY_GNUPG_H
39
40#include <libetpan/mailprivacy_types.h>
41
42int mailprivacy_gnupg_init(struct mailprivacy * privacy);
43
44void mailprivacy_gnupg_done(struct mailprivacy * privacy);
45
46#endif
diff --git a/libetpan/include/libetpan/mailprivacy_smime.h b/libetpan/include/libetpan/mailprivacy_smime.h
new file mode 100644
index 0000000..85d9e40
--- a/dev/null
+++ b/libetpan/include/libetpan/mailprivacy_smime.h
@@ -0,0 +1,84 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPRIVACY_SMIME_H
37
38#define MAILPRIVACY_SMIME_H
39
40#include <libetpan/mailprivacy_types.h>
41
42int mailprivacy_smime_init(struct mailprivacy * privacy);
43
44void mailprivacy_smime_done(struct mailprivacy * privacy);
45
46void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy,
47 char * directory);
48
49
50/*
51 set directory where certificates of authority certifications are
52 stored.
53*/
54
55void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy,
56 char * directory);
57
58
59/*
60 to disable the verification of signers certificates of a
61 signed message.
62*/
63
64void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy,
65 int enabled);
66
67
68/*
69 to store certificates of signed messages
70*/
71
72void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy,
73 int enabled);
74
75/*
76 set directory where private keys are stored.
77 name of the files in that directory must be in form :
78 [email-address]-private-key.pem
79*/
80
81void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy,
82 char * directory);
83
84#endif
diff --git a/libetpan/include/libetpan/mailprivacy_tools.h b/libetpan/include/libetpan/mailprivacy_tools.h
new file mode 100644
index 0000000..1bf27c4
--- a/dev/null
+++ b/libetpan/include/libetpan/mailprivacy_tools.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_TOOLS_H
37
38#define MAIL_PRIVACY_TOOLS_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailprivacy_types.h>
42
43void mailprivacy_mime_clear(struct mailmime * mime);
44
45FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy,
46 char * filename, size_t size);
47
48int mailprivacy_get_mime(struct mailprivacy * privacy,
49 int check_privacy,
50 char * content, size_t content_len,
51 struct mailmime ** result_mime);
52
53struct mailmime *
54mailprivacy_new_file_part(struct mailprivacy * privacy,
55 char * filename,
56 char * default_content_type, int default_encoding);
57
58int mailmime_substitute(struct mailmime * old_mime,
59 struct mailmime * new_mime);
60
61int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy,
62 char * filename, size_t size,
63 mailmessage * msg, struct mailmime * mime);
64
65int mailprivacy_get_part_from_file(struct mailprivacy * privacy,
66 int check_privacy,
67 char * filename,
68 struct mailmime ** result_mime);
69
70int mail_quote_filename(char * result, size_t size, char * path);
71
72void mailprivacy_prepare_mime(struct mailmime * mime);
73
74char * mailprivacy_dup_imf_file(struct mailprivacy * privacy,
75 char * source_filename);
76
77struct mailmime_fields *
78mailprivacy_mime_fields_dup(struct mailprivacy * privacy,
79 struct mailmime_fields * mime_fields);
80
81struct mailmime_parameter *
82mailmime_parameter_dup(struct mailmime_parameter * param);
83
84struct mailmime_composite_type *
85mailmime_composite_type_dup(struct mailmime_composite_type * composite_type);
86
87struct mailmime_discrete_type *
88mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type);
89
90struct mailmime_type * mailmime_type_dup(struct mailmime_type * type);
91
92struct mailmime_content *
93mailmime_content_dup(struct mailmime_content * content);
94
95struct mailmime_parameter *
96mailmime_param_new_with_data(char * name, char * value);
97
98int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy,
99 char * filename, size_t size,
100 mailmessage * msg, struct mailmime * mime);
101
102#endif
diff --git a/libetpan/include/libetpan/mailprivacy_types.h b/libetpan/include/libetpan/mailprivacy_types.h
new file mode 100644
index 0000000..e53f226
--- a/dev/null
+++ b/libetpan/include/libetpan/mailprivacy_types.h
@@ -0,0 +1,82 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_TYPES_H
37
38#define MAIL_PRIVACY_TYPES_H
39
40#include <libetpan/chash.h>
41#include <libetpan/carray.h>
42#include <libetpan/mailmessage.h>
43#include <libetpan/mailmime.h>
44
45struct mailprivacy {
46 char * tmp_dir; /* working tmp directory */
47 chash * msg_ref; /* mailmessage => present or not */
48 chash * mmapstr; /* mmapstring => present or not present */
49 chash * mime_ref; /* mime => present or not */
50 carray * protocols;
51 int make_alternative;
52 /* if make_alternative is 0, replaces the part with decrypted
53 part, if 1, adds a multipart/alternative and put the decrypted
54 and encrypted part as subparts.
55 */
56};
57
58struct mailprivacy_encryption {
59 char * name;
60 char * description;
61
62 int (* encrypt)(struct mailprivacy *,
63 struct mailmime *, struct mailmime **);
64};
65
66struct mailprivacy_protocol {
67 char * name;
68 char * description;
69
70 /* introduce to easy the port to sylpheed */
71 int (* is_encrypted)(struct mailprivacy *,
72 mailmessage *, struct mailmime *);
73
74 int (* decrypt)(struct mailprivacy *,
75 mailmessage *, struct mailmime *,
76 struct mailmime **);
77
78 int encryption_count;
79 struct mailprivacy_encryption * encryption_tab;
80};
81
82#endif
diff --git a/libetpan/include/libetpan/mailsem.h b/libetpan/include/libetpan/mailsem.h
new file mode 100644
index 0000000..3a6d7bc
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsem.h
@@ -0,0 +1,51 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSEM_H
37
38#define MAILSEM_H
39
40struct mailsem {
41 void * sem_sem;
42 int sem_kind;
43};
44
45struct mailsem * mailsem_new(void);
46void mailsem_free(struct mailsem * sem);
47
48int mailsem_up(struct mailsem * sem);
49int mailsem_down(struct mailsem * sem);
50
51#endif
diff --git a/libetpan/include/libetpan/mailsmtp.h b/libetpan/include/libetpan/mailsmtp.h
new file mode 100644
index 0000000..72e1786
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsmtp.h
@@ -0,0 +1,94 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_H
37
38#define MAILSMTP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailsmtp_types.h>
45#include <libetpan/mailsmtp_helper.h>
46#include <libetpan/mailsmtp_socket.h>
47#include <libetpan/mailsmtp_ssl.h>
48
49
50mailsmtp * mailsmtp_new(size_t progr_rate,
51 progress_function * progr_fun);
52void mailsmtp_free(mailsmtp * session);
53
54int mailsmtp_connect(mailsmtp * session, mailstream * s);
55int mailsmtp_quit(mailsmtp * session);
56
57/**
58 * Tries AUTH with detected method - "better" method first:
59 * CRAM-MD5 -> PLAIN -> LOGIN
60 */
61int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass);
62
63/**
64 * tries to autenticate with the server using given auth-type
65 * returns MAILSMTP_NO_ERROR on success
66 */
67int mailsmtp_auth_type(mailsmtp * session,
68 const char * user, const char * pass, int type);
69
70int mailsmtp_helo(mailsmtp * session);
71int mailsmtp_mail(mailsmtp * session, const char * from);
72int mailsmtp_rcpt(mailsmtp * session, const char * to);
73int mailsmtp_data(mailsmtp * session);
74int mailsmtp_data_message(mailsmtp * session,
75 const char * message,
76 size_t size);
77int mailesmtp_ehlo(mailsmtp * session);
78int mailesmtp_mail(mailsmtp * session,
79 const char * from,
80 int return_full,
81 const char * envid);
82int mailesmtp_rcpt(mailsmtp * session,
83 const char * to,
84 int notify,
85 const char * orcpt);
86int mailesmtp_starttls(mailsmtp * session);
87
88const char * mailsmtp_strerror(int errnum);
89
90#ifdef __cplusplus
91}
92#endif
93
94#endif
diff --git a/libetpan/include/libetpan/mailsmtp_helper.h b/libetpan/include/libetpan/mailsmtp_helper.h
new file mode 100644
index 0000000..2178d50
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsmtp_helper.h
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_HELPER_H
37
38#define MAILSMTP_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailsmtp_types.h"
45#include "clist.h"
46
47int mailsmtp_init(mailsmtp * session);
48
49int mailesmtp_send(mailsmtp * session,
50 const char * from,
51 int return_full,
52 const char * envid,
53 clist * addresses,
54 const char * message, size_t size);
55
56int mailsmtp_send(mailsmtp * session,
57 const char * from,
58 clist * addresses,
59 const char * message, size_t size);
60
61clist * esmtp_address_list_new();
62int esmtp_address_list_add(clist * list, char * address,
63 int notify, char * orcpt);
64void esmtp_address_list_free(clist * l);
65
66clist * smtp_address_list_new();
67int smtp_address_list_add(clist * list, char * address);
68void smtp_address_list_free(clist * l);
69
70#ifdef __cplusplus
71}
72#endif
73
74#endif
diff --git a/libetpan/include/libetpan/mailsmtp_socket.h b/libetpan/include/libetpan/mailsmtp_socket.h
new file mode 100644
index 0000000..2726c1d
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsmtp_socket.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SOCKET_H
37
38#define MAILSMTP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_socket_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50int mailsmtp_socket_starttls(mailsmtp * session);
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/include/libetpan/mailsmtp_ssl.h b/libetpan/include/libetpan/mailsmtp_ssl.h
new file mode 100644
index 0000000..01f4683
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsmtp_ssl.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SSL_H
37
38#define MAILSMTP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_ssl_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/include/libetpan/mailsmtp_types.h b/libetpan/include/libetpan/mailsmtp_types.h
new file mode 100644
index 0000000..0aa2617
--- a/dev/null
+++ b/libetpan/include/libetpan/mailsmtp_types.h
@@ -0,0 +1,126 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_TYPES_H
37
38#define MAILSMTP_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstream.h"
45#include "mmapstring.h"
46
47enum {
48 MAILSMTP_NO_ERROR = 0,
49 MAILSMTP_ERROR_UNEXPECTED_CODE,
50 MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE,
51 MAILSMTP_ERROR_STREAM,
52 MAILSMTP_ERROR_HOSTNAME,
53 MAILSMTP_ERROR_NOT_IMPLEMENTED,
54 MAILSMTP_ERROR_ACTION_NOT_TAKEN,
55 MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION,
56 MAILSMTP_ERROR_IN_PROCESSING,
57 MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE,
58 MAILSMTP_ERROR_MAILBOX_UNAVAILABLE,
59 MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED,
60 MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND,
61 MAILSMTP_ERROR_USER_NOT_LOCAL,
62 MAILSMTP_ERROR_TRANSACTION_FAILED,
63 MAILSMTP_ERROR_MEMORY,
64 MAILSMTP_ERROR_AUTH_NOT_SUPPORTED,
65 MAILSMTP_ERROR_AUTH_LOGIN,
66 MAILSMTP_ERROR_AUTH_REQUIRED,
67 MAILSMTP_ERROR_AUTH_TOO_WEAK,
68 MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED,
69 MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE,
70 MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED,
71 MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE,
72 MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED,
73 MAILSMTP_ERROR_CONNECTION_REFUSED
74};
75
76enum {
77 MAILSMTP_AUTH_NOT_CHECKED = 0,
78 MAILSMTP_AUTH_CHECKED = 1,
79 MAILSMTP_AUTH_CRAM_MD5 = 2,
80 MAILSMTP_AUTH_PLAIN = 4,
81 MAILSMTP_AUTH_LOGIN = 8
82};
83
84enum {
85 MAILSMTP_ESMTP = 1,
86 MAILSMTP_ESMTP_EXPN = 2,
87 MAILSMTP_ESMTP_8BITMIME = 4,
88 MAILSMTP_ESMTP_SIZE = 8,
89 MAILSMTP_ESMTP_ETRN = 16,
90 MAILSMTP_ESMTP_STARTTLS = 32,
91 MAILSMTP_ESMTP_DSN = 64,
92};
93
94struct mailsmtp {
95 mailstream * stream;
96
97 size_t progr_rate;
98 progress_function * progr_fun;
99
100 char * response;
101
102 MMAPString * line_buffer;
103 MMAPString * response_buffer;
104
105 int esmtp; // contains flags MAILSMTP_ESMTP_*
106 int auth; // contains flags MAILSMTP_AUTH_*
107};
108
109typedef struct mailsmtp mailsmtp;
110
111#define MAILSMTP_DSN_NOTIFY_SUCCESS 1
112#define MAILSMTP_DSN_NOTIFY_FAILURE 2
113#define MAILSMTP_DSN_NOTIFY_DELAY 4
114#define MAILSMTP_DSN_NOTIFY_NEVER 8
115
116struct esmtp_address {
117 char * address;
118 int notify;
119 char * orcpt;
120};
121
122#ifdef __cplusplus
123}
124#endif
125
126#endif
diff --git a/libetpan/include/libetpan/mailstorage.h b/libetpan/include/libetpan/mailstorage.h
new file mode 100644
index 0000000..e8cbda3
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstorage.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_STORAGE_H
37
38#define MAIL_STORAGE_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailstorage_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* storage */
48
49/*
50 mailstorage_new
51
52 This function creates an empty storage. This storage have to be initialized.
53 The "driver" and "data" fields should be initialized.
54
55 @param id is the name of the storage. It can be NULL.
56 The given parameter is no more needed when the creation is finished.
57 The given string is duplicated.
58
59 @return The mail storage is returned.
60*/
61
62struct mailstorage * mailstorage_new(char * sto_id);
63
64void mailstorage_free(struct mailstorage * storage);
65
66/*
67 session will be initialized on success.
68*/
69
70int mailstorage_connect(struct mailstorage * storage);
71
72void mailstorage_disconnect(struct mailstorage * storage);
73
74int mailstorage_noop(struct mailstorage * storage);
75
76
77/* folder */
78
79struct mailfolder * mailfolder_new(struct mailstorage * fld_storage,
80 char * fld_pathname, char * fld_virtual_name);
81
82void mailfolder_free(struct mailfolder * folder);
83
84int mailfolder_add_child(struct mailfolder * parent,
85 struct mailfolder * child);
86
87int mailfolder_detach_parent(struct mailfolder * folder);
88
89int mailfolder_connect(struct mailfolder * folder);
90
91void mailfolder_disconnect(struct mailfolder * folder);
92
93#ifdef __cplusplus
94}
95#endif
96
97#endif
98
99
diff --git a/libetpan/include/libetpan/mailstorage_types.h b/libetpan/include/libetpan/mailstorage_types.h
new file mode 100644
index 0000000..d0d18c8
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstorage_types.h
@@ -0,0 +1,203 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTORAGE_TYPES_H
37
38#define MAILSTORAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46struct mailstorage;
47
48typedef struct mailstorage_driver mailstorage_driver;
49
50
51/*
52 There is three kinds of identities :
53 - storage
54 - folders
55 - session
56
57 A storage (struct mailstorage) represents whether a server or
58 a main path,
59
60 A storage can be an IMAP server, the root path of a MH or a mbox file.
61
62 Folders (struct mailfolder) are the mailboxes we can
63 choose in the server or as sub-folder of the main path.
64
65 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
66 folder of the MH storage, for mbox, there is only one folder, the
67 mbox file content;
68
69 A mail session (struct mailsession) is whether a connection to a server
70 or a path that is open. It is the abstraction lower folders and storage.
71 It allow us to send commands.
72
73 We have a session driver for mail session for each kind of storage.
74
75 From a session, we can get a message (struct mailmessage) to read.
76 We have a message driver for each kind of storage.
77*/
78
79/*
80 mailstorage_driver is the driver structure for mail storages
81
82 - name is the name of the driver
83
84 - connect() connects the storage to the remote access or to
85 the path in the local filesystem.
86
87 - get_folder() can have two kinds of behaviour.
88 Either it creates a new session and independant from the session
89 used by the storage and select the given mailbox or
90 it selects the given mailbox in the current session.
91 It depends on the efficiency of the mail driver.
92
93 - uninitialize() frees the data created with mailstorage constructor.
94*/
95
96struct mailstorage_driver {
97 char * sto_name;
98 int (* sto_connect)(struct mailstorage * storage);
99 int (* sto_get_folder_session)(struct mailstorage * storage,
100 char * pathname, mailsession ** result);
101 void (* sto_uninitialize)(struct mailstorage * storage);
102};
103
104/*
105 mailstorage is the data structure for a storage
106
107 - id is the name of the storage, it can be NULL.
108
109 - data is the data specific to the driver.
110 This is the internal state of the storage.
111
112 - session is the session related to the storage.
113
114 - driver is the driver for the storage.
115
116 - shared_folders is the list of folders returned by the storage.
117*/
118
119struct mailstorage {
120 char * sto_id;
121 void * sto_data;
122 mailsession * sto_session;
123 mailstorage_driver * sto_driver;
124 clist * sto_shared_folders; /* list of (struct mailfolder *) */
125
126 void * sto_user_data;
127};
128
129
130
131/*
132 mailfolder is the data structure for a mailbox
133
134 - pathname is the path of the mailbox on the storage
135
136 - virtual_name is the folder identifier, it can be a path,
137 a name or NULL.
138
139 - storage is the storage to which the folder belongs to.
140
141 - session is the session related to the folder. It can be
142 different of the session of the storage.
143
144 - shared_session is != 0 if the session is the same as the
145 session of the storage.
146
147 - pos is the position of the folder in the "shared_folders" field
148 of the storage.
149
150 folders can be chained into a tree.
151
152 - parent is the parent of the folder.
153
154 - sibling_index is the index of the folder in the list of children
155 of the parent.
156
157 - children is the folder.
158*/
159
160struct mailfolder {
161 char * fld_pathname;
162 char * fld_virtual_name;
163
164 struct mailstorage * fld_storage;
165
166 mailsession * fld_session;
167 int fld_shared_session;
168 clistiter * fld_pos;
169
170 struct mailfolder * fld_parent;
171 unsigned int fld_sibling_index;
172 carray * fld_children; /* array of (struct mailfolder *) */
173
174 void * fld_user_data;
175};
176
177/*
178 this is the type of socket connection
179*/
180
181enum {
182 CONNECTION_TYPE_PLAIN, /* when the connection is plain text */
183 CONNECTION_TYPE_STARTTLS, /* when the connection is first plain,
184 then, we want to switch to
185 TLS (secure connection) */
186 CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain,
187 then, we will try to switch to TLS */
188 CONNECTION_TYPE_TLS, /* the connection is over TLS */
189 CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */
190 CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell
191 command and STARTTLS will be used */
192 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over
193 a shell command and STARTTLS will
194 be tried */
195 CONNECTION_TYPE_COMMAND_TLS, /* the connection is over a shell
196 command in TLS */
197};
198
199#ifdef __cplusplus
200}
201#endif
202
203#endif
diff --git a/libetpan/include/libetpan/mailstream.h b/libetpan/include/libetpan/mailstream.h
new file mode 100644
index 0000000..04a5ae3
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_H
37
38#define MAILSTREAM_H
39
40#include <sys/time.h>
41
42#include <libetpan/mailstream_low.h>
43#include <libetpan/mailstream_helper.h>
44#include <libetpan/mailstream_socket.h>
45#include <libetpan/mailstream_ssl.h>
46#include <libetpan/mailstream_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52mailstream * mailstream_new(mailstream_low * low, size_t buffer_size);
53ssize_t mailstream_write(mailstream * s, const void * buf, size_t count);
54ssize_t mailstream_read(mailstream * s, void * buf, size_t count);
55int mailstream_close(mailstream * s);
56int mailstream_flush(mailstream * s);
57ssize_t mailstream_feed_read_buffer(mailstream * s);
58mailstream_low * mailstream_get_low(mailstream * s);
59void mailstream_set_low(mailstream * s, mailstream_low * low);
60
61#ifdef LIBETPAN_MAILSTREAM_DEBUG
62extern int mailstream_debug;
63#endif
64
65#define LIBETPAN_MAILSTREAM_NETWORK_DELAY
66extern struct timeval mailstream_network_delay;
67
68#ifdef __cplusplus
69}
70#endif
71
72#endif
73
diff --git a/libetpan/include/libetpan/mailstream_helper.h b/libetpan/include/libetpan/mailstream_helper.h
new file mode 100644
index 0000000..1bc36a2
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream_helper.h
@@ -0,0 +1,77 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_HELPER_H
37
38#define MAILSTREAM_HELPER_H
39
40#include <libetpan/mmapstring.h>
41#include <libetpan/mailstream.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47char * mailstream_read_line(mailstream * stream, MMAPString * line);
48
49char * mailstream_read_line_append(mailstream * stream, MMAPString * line);
50
51char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line);
52
53char * mailstream_read_multiline(mailstream * s, size_t size,
54 MMAPString * stream_buffer,
55 MMAPString * multiline_buffer,
56 size_t progr_rate,
57 progress_function * progr_fun);
58
59int mailstream_is_end_multiline(const char * line);
60
61int mailstream_send_data_crlf(mailstream * s, const char * message,
62 size_t size,
63 size_t progr_rate,
64 progress_function * progr_fun);
65
66int mailstream_send_data(mailstream * s, const char * message,
67 size_t size,
68 size_t progr_rate,
69 progress_function * progr_fun);
70
71size_t mailstream_get_data_crlf_size(const char * message, size_t size);
72
73#ifdef __cplusplus
74}
75#endif
76
77#endif
diff --git a/libetpan/include/libetpan/mailstream_low.h b/libetpan/include/libetpan/mailstream_low.h
new file mode 100644
index 0000000..e3fff1f
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream_low.h
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_LOW_H
37
38#define MAILSTREAM_LOW_H
39
40#include <sys/types.h>
41#include <libetpan/mailstream_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* general functions */
48
49mailstream_low * mailstream_low_new(void * data,
50 mailstream_low_driver * driver);
51ssize_t mailstream_low_write(mailstream_low * s,
52 const void * buf, size_t count);
53ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count);
54int mailstream_low_close(mailstream_low * s);
55int mailstream_low_get_fd(mailstream_low * s);
56void mailstream_low_free(mailstream_low * s);
57
58#ifdef __cplusplus
59}
60#endif
61
62#endif
diff --git a/libetpan/include/libetpan/mailstream_socket.h b/libetpan/include/libetpan/mailstream_socket.h
new file mode 100644
index 0000000..9cf6ada
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream_socket.h
@@ -0,0 +1,61 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_SOCKET_H
37
38#define MAILSTREAM_SOCKET_H
39
40#include <libetpan/mailstream.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* socket */
47
48extern mailstream_low_driver * mailstream_socket_driver;
49
50mailstream_low * mailstream_low_socket_open(int fd);
51mailstream * mailstream_socket_open(int fd);
52
53struct mailstream_socket_data {
54 int fd;
55};
56
57#ifdef __cplusplus
58}
59#endif
60
61#endif
diff --git a/libetpan/include/libetpan/mailstream_ssl.h b/libetpan/include/libetpan/mailstream_ssl.h
new file mode 100644
index 0000000..bc14d25
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream_ssl.h
@@ -0,0 +1,59 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_SSL_H
37
38#define MAILSTREAM_SSL_H
39
40#include <libetpan/mailstream.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* socket */
47
48#ifdef USE_SSL
49extern mailstream_low_driver * mailstream_ssl_driver;
50#endif
51
52mailstream_low * mailstream_low_ssl_open(int fd);
53mailstream * mailstream_ssl_open(int fd);
54
55#ifdef __cplusplus
56}
57#endif
58
59#endif
diff --git a/libetpan/include/libetpan/mailstream_types.h b/libetpan/include/libetpan/mailstream_types.h
new file mode 100644
index 0000000..b560ebb
--- a/dev/null
+++ b/libetpan/include/libetpan/mailstream_types.h
@@ -0,0 +1,87 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_TYPES_H
37
38#define MAILSTREAM_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#define LIBETPAN_MAILSTREAM_DEBUG
45
46struct _mailstream;
47
48typedef struct _mailstream mailstream;
49
50struct _mailstream_low;
51
52typedef struct _mailstream_low mailstream_low;
53
54struct _mailstream {
55 size_t buffer_max_size;
56
57 char * write_buffer;
58 size_t write_buffer_len;
59
60 char * read_buffer;
61 size_t read_buffer_len;
62
63 mailstream_low * low;
64};
65
66struct mailstream_low_driver {
67 ssize_t (* mailstream_read)(mailstream_low *, void *, size_t);
68 ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t);
69 int (* mailstream_close)(mailstream_low *);
70 int (* mailstream_get_fd)(mailstream_low *);
71 void (* mailstream_free)(mailstream_low *);
72};
73
74typedef struct mailstream_low_driver mailstream_low_driver;
75
76struct _mailstream_low {
77 void * data;
78 mailstream_low_driver * driver;
79};
80
81typedef void progress_function(size_t current, size_t maximum);
82
83#ifdef __cplusplus
84}
85#endif
86
87#endif
diff --git a/libetpan/include/libetpan/mailthread.h b/libetpan/include/libetpan/mailthread.h
new file mode 100644
index 0000000..fa2f4bc
--- a/dev/null
+++ b/libetpan/include/libetpan/mailthread.h
@@ -0,0 +1,108 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_H
37
38#define MAILTHREAD_H
39
40#include <libetpan/mailthread_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_build_thread constructs a tree with the message using the
48 given style.
49
50 @param type is the type of threading to apply, the value can be
51 MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT,
52 MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE,
53
54 @param default_from is the default charset to use whenever the
55 subject is not tagged with a charset. "US-ASCII" can be used
56 if you don't know what to use.
57
58 @param env_list is the message list (with header fields fetched)
59 to use to build the message tree.
60
61 @param result * result) will contain the resulting message tree.
62
63 @param if comp_func is NULL, no sorting algorithm is used.
64
65 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
66 on error
67*/
68
69int mail_build_thread(int type, char * default_from,
70 struct mailmessage_list * env_list,
71 struct mailmessage_tree ** result,
72 int (* comp_func)(struct mailmessage_tree **,
73 struct mailmessage_tree **));
74
75/*
76 mail_thread_sort sort the messages in the message tree, using the
77 given sort function.
78
79 @param tree is the message tree to sort.
80
81 @param comp_func is the sort function to use (this is the same kind of
82 functions than those used for qsort()). mailthread_tree_timecomp can be
83 used for default sort.
84
85 @param sort_sub if this value is 0, only the children of the root message
86 are sorted.
87*/
88
89int mail_thread_sort(struct mailmessage_tree * tree,
90 int (* comp_func)(struct mailmessage_tree **,
91 struct mailmessage_tree **),
92 int sort_sub);
93
94/*
95 mailthread_tree_timecomp is the default sort function.
96
97 The message are compared by date, then by message numbers.
98 The tree are given in (* ptree1) and (* ptree2).
99*/
100
101int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1,
102 struct mailmessage_tree ** ptree2);
103
104#ifdef __cplusplus
105}
106#endif
107
108#endif
diff --git a/libetpan/include/libetpan/mailthread_types.h b/libetpan/include/libetpan/mailthread_types.h
new file mode 100644
index 0000000..3325904
--- a/dev/null
+++ b/libetpan/include/libetpan/mailthread_types.h
@@ -0,0 +1,64 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_TYPES_H
37
38#define MAILTHREAD_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/maildriver_types.h>
45#include <libetpan/mailmessage_types.h>
46
47/*
48 This is the type of tree construction to apply.
49*/
50
51enum {
52 MAIL_THREAD_REFERENCES, /* this is threading using
53 References fields only) */
54 MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References
55 fields, then subject */
56 MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */
57 MAIL_THREAD_NONE, /* no thread */
58};
59
60#ifdef __cplusplus
61}
62#endif
63
64#endif
diff --git a/libetpan/include/libetpan/mboxdriver.h b/libetpan/include/libetpan/mboxdriver.h
new file mode 100644
index 0000000..9b37aa4
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_H
37
38#define MBOXDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mboxdriver_types.h>
45
46extern mailsession_driver * mbox_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mboxdriver_cached.h b/libetpan/include/libetpan/mboxdriver_cached.h
new file mode 100644
index 0000000..25c4027
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxdriver_cached.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_H
37
38#define MBOXDRIVER_CACHED_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mboxdriver_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48extern mailsession_driver * mbox_cached_session_driver;
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/include/libetpan/mboxdriver_cached_message.h b/libetpan/include/libetpan/mboxdriver_cached_message.h
new file mode 100644
index 0000000..144e2da
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_MESSAGE_H
37
38#define MBOXDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mailmessage.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mboxdriver_message.h b/libetpan/include/libetpan/mboxdriver_message.h
new file mode 100644
index 0000000..686e46e
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_MESSAGE_H
37
38#define MBOXDRIVER_MESSAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mboxdriver_types.h b/libetpan/include/libetpan/mboxdriver_types.h
new file mode 100644
index 0000000..23b9acf
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxdriver_types.h
@@ -0,0 +1,107 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_TYPES_H
37
38#define MBOXDRIVER_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailmbox.h>
42#include <libetpan/mailstorage_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/* mbox driver */
49
50enum {
51 MBOXDRIVER_SET_READ_ONLY = 1,
52 MBOXDRIVER_SET_NO_UID,
53};
54
55struct mbox_session_state_data {
56 struct mailmbox_folder * mbox_folder;
57 int mbox_force_read_only;
58 int mbox_force_no_uid;
59};
60
61/* cached version */
62
63enum {
64 /* the mapping of the parameters should be the same as for mbox */
65 MBOXDRIVER_CACHED_SET_READ_ONLY = 1,
66 MBOXDRIVER_CACHED_SET_NO_UID,
67 /* cache specific */
68 MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
69 MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
70};
71
72struct mbox_cached_session_state_data {
73 mailsession * mbox_ancestor;
74 char * mbox_quoted_mb;
75 char mbox_cache_directory[PATH_MAX];
76 char mbox_flags_directory[PATH_MAX];
77 struct mail_flags_store * mbox_flags_store;
78};
79
80/* mbox storage */
81
82/*
83 mbox_mailstorage is the state data specific to the mbox storage.
84
85 - pathname is the filename that contains the mailbox.
86
87 - cached if this value is != 0, a persistant cache will be
88 stored on local system.
89
90 - cache_directory is the location of the cache.
91
92 - flags_directory is the location of the flags.
93*/
94
95struct mbox_mailstorage {
96 char * mbox_pathname;
97
98 int mbox_cached;
99 char * mbox_cache_directory;
100 char * mbox_flags_directory;
101};
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif
diff --git a/libetpan/include/libetpan/mboxstorage.h b/libetpan/include/libetpan/mboxstorage.h
new file mode 100644
index 0000000..45aed7b
--- a/dev/null
+++ b/libetpan/include/libetpan/mboxstorage.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXSTORAGE_H
37
38#define MBOXSTORAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mbox_mailstorage_init is the constructor for a mbox storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the filename that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int mbox_mailstorage_init(struct mailstorage * storage,
62 char * mb_pathname, int mb_cached,
63 char * mb_cache_directory, char * mb_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/include/libetpan/mhdriver.h b/libetpan/include/libetpan/mhdriver.h
new file mode 100644
index 0000000..a3f45f5
--- a/dev/null
+++ b/libetpan/include/libetpan/mhdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_H
37
38#define MHDRIVER_H
39
40#include <libetpan/maildriver.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mhdriver_cached.h b/libetpan/include/libetpan/mhdriver_cached.h
new file mode 100644
index 0000000..d2e5803
--- a/dev/null
+++ b/libetpan/include/libetpan/mhdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_H
37
38#define MHDRIVER_CACHED_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mhdriver_cached_message.h b/libetpan/include/libetpan/mhdriver_cached_message.h
new file mode 100644
index 0000000..f585708
--- a/dev/null
+++ b/libetpan/include/libetpan/mhdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_MESSAGE_H
37
38#define MHDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mhdriver_message.h b/libetpan/include/libetpan/mhdriver_message.h
new file mode 100644
index 0000000..2b11f3e
--- a/dev/null
+++ b/libetpan/include/libetpan/mhdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_MESSAGE_H
37
38#define MHDRIVER_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/mhdriver_types.h b/libetpan/include/libetpan/mhdriver_types.h
new file mode 100644
index 0000000..45afb64
--- a/dev/null
+++ b/libetpan/include/libetpan/mhdriver_types.h
@@ -0,0 +1,100 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_TYPES_H
37
38#define MHDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailmh.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52struct mh_session_state_data {
53 struct mailmh * mh_session;
54
55 struct mailmh_folder * mh_cur_folder;
56
57 clist * mh_subscribed_list;
58};
59
60enum {
61 MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
62 MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
63};
64
65struct mh_cached_session_state_data {
66 mailsession * mh_ancestor;
67 char * mh_quoted_mb;
68 char mh_cache_directory[PATH_MAX];
69 char mh_flags_directory[PATH_MAX];
70 struct mail_flags_store * mh_flags_store;
71};
72
73/* mh storage */
74
75/*
76 mh_mailstorage is the state data specific to the MH storage.
77
78 - pathname is the root path of the MH storage.
79
80 - cached if this value is != 0, a persistant cache will be
81 stored on local system.
82
83 - cache_directory is the location of the cache.
84
85 - flags_directory is the location of the flags.
86*/
87
88struct mh_mailstorage {
89 char * mh_pathname;
90
91 int mh_cached;
92 char * mh_cache_directory;
93 char * mh_flags_directory;
94};
95
96#ifdef __cplusplus
97}
98#endif
99
100#endif
diff --git a/libetpan/include/libetpan/mhstorage.h b/libetpan/include/libetpan/mhstorage.h
new file mode 100644
index 0000000..be86007
--- a/dev/null
+++ b/libetpan/include/libetpan/mhstorage.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHSTORAGE_H
37
38#define MHSTORAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mh_mailstorage_init is the constructor for a MH storage
48
49 @param pathname is the filename the root path of the MH storage.
50
51 @param cached if this value is != 0, a persistant cache will be
52 stored on local system.
53
54 @param cache_directory is the location of the cache.
55
56 @param flags_directory is the location of the flags.
57*/
58
59int mh_mailstorage_init(struct mailstorage * storage,
60 char * mh_pathname, int mh_cached,
61 char * mh_cache_directory, char * mh_flags_directory);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/include/libetpan/mime_message_driver.h b/libetpan/include/libetpan/mime_message_driver.h
new file mode 100644
index 0000000..6cc3c5b
--- a/dev/null
+++ b/libetpan/include/libetpan/mime_message_driver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MIME_MESSAGE_DRIVER_H
37
38#define MIME_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_MIME_MESSAGE
43
44extern mailmessage_driver * mime_message_driver;
45
46mailmessage * mime_message_init(struct mailmime * mime);
47
48void mime_message_detach_mime(mailmessage * msg);
49
50/* deprecated */
51int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir);
52
53#endif
diff --git a/libetpan/include/libetpan/mmapstring.h b/libetpan/include/libetpan/mmapstring.h
new file mode 100644
index 0000000..573e354
--- a/dev/null
+++ b/libetpan/include/libetpan/mmapstring.h
@@ -0,0 +1,136 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef __MMAP_STRING_H__
37
38#define __MMAP_STRING_H__
39
40#include <sys/types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47#define TMPDIR "/tmp"
48*/
49
50typedef struct _MMAPString MMAPString;
51
52struct _MMAPString
53{
54 char * str;
55 size_t len;
56 size_t allocated_len;
57 int fd;
58 size_t mmapped_size;
59 /*
60 char * old_non_mmapped_str;
61 */
62};
63
64/* configure location of mmaped files */
65
66void mmap_string_set_tmpdir(char * directory);
67
68/* Strings
69 */
70
71MMAPString * mmap_string_new (const char * init);
72
73MMAPString * mmap_string_new_len (const char * init,
74 size_t len);
75
76MMAPString * mmap_string_sized_new (size_t dfl_size);
77
78void mmap_string_free (MMAPString * string);
79
80MMAPString * mmap_string_assign (MMAPString * string,
81 const char * rval);
82
83MMAPString * mmap_string_truncate (MMAPString *string,
84 size_t len);
85
86MMAPString * mmap_string_set_size (MMAPString * string,
87 size_t len);
88
89MMAPString * mmap_string_insert_len (MMAPString * string,
90 size_t pos,
91 const char * val,
92 size_t len);
93
94MMAPString * mmap_string_append (MMAPString * string,
95 const char * val);
96
97MMAPString * mmap_string_append_len (MMAPString * string,
98 const char * val,
99 size_t len);
100
101MMAPString * mmap_string_append_c (MMAPString * string,
102 char c);
103
104MMAPString * mmap_string_prepend (MMAPString * string,
105 const char * val);
106
107MMAPString * mmap_string_prepend_c (MMAPString * string,
108 char c);
109
110MMAPString * mmap_string_prepend_len (MMAPString * string,
111 const char * val,
112 size_t len);
113
114MMAPString * mmap_string_insert (MMAPString * string,
115 size_t pos,
116 const char * val);
117
118MMAPString * mmap_string_insert_c (MMAPString *string,
119 size_t pos,
120 char c);
121
122MMAPString * mmap_string_erase(MMAPString * string,
123 size_t pos,
124 size_t len);
125
126void mmap_string_set_ceil(size_t ceil);
127
128int mmap_string_ref(MMAPString * string);
129int mmap_string_unref(char * str);
130
131#ifdef __cplusplus
132}
133#endif
134
135
136#endif /* __MMAP_STRING_H__ */
diff --git a/libetpan/include/libetpan/newsnntp.h b/libetpan/include/libetpan/newsnntp.h
new file mode 100644
index 0000000..dd65ee2
--- a/dev/null
+++ b/libetpan/include/libetpan/newsnntp.h
@@ -0,0 +1,187 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_H
37
38#define NEWSNNTP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <sys/types.h>
46#include <time.h>
47
48#include <libetpan/clist.h>
49#include <libetpan/mailstream.h>
50#include <libetpan/newsnntp_socket.h>
51#include <libetpan/newsnntp_ssl.h>
52#include <libetpan/newsnntp_types.h>
53
54
55newsnntp * newsnntp_new(size_t nntp_progr_rate,
56 progress_function * nntp_progr_fun);
57void newsnntp_free(newsnntp * f);
58
59int newsnntp_quit(newsnntp * f);
60int newsnntp_connect(newsnntp * f, mailstream * s);
61
62int newsnntp_head(newsnntp * f, uint32_t index, char ** result,
63 size_t * result_len);
64int newsnntp_article(newsnntp * f, uint32_t index, char ** result,
65 size_t * result_len);
66int newsnntp_body(newsnntp * f, uint32_t index, char ** result,
67 size_t * result_len);
68
69void newsnntp_head_free(char * str);
70void newsnntp_article_free(char * str);
71void newsnntp_body_free(char * str);
72
73int newsnntp_mode_reader(newsnntp * f);
74
75int newsnntp_date(newsnntp * f, struct tm * tm);
76
77int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator,
78 const char * arguments);
79
80int newsnntp_authinfo_username(newsnntp * f, const char * username);
81int newsnntp_authinfo_password(newsnntp * f, const char * password);
82
83int newsnntp_post(newsnntp * f, const char * message, size_t size);
84
85
86
87
88
89
90/******************* requests ******************************/
91
92int newsnntp_group(newsnntp * f, const char * groupname,
93 struct newsnntp_group_info ** info);
94void newsnntp_group_free(struct newsnntp_group_info * info);
95
96/*
97 elements are struct newsnntp_group_info *
98 */
99
100int newsnntp_list(newsnntp * f, clist ** result);
101void newsnntp_list_free(clist * l);
102
103/*
104 elements are char *
105*/
106
107int newsnntp_list_overview_fmt(newsnntp * f, clist ** result);
108void newsnntp_list_overview_fmt_free(clist * l);
109
110/*
111 elements are struct newsnntp_group_info *
112*/
113
114int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result);
115void newsnntp_list_active_free(clist * l);
116
117/*
118 elements are struct newsnntp_group_time *
119*/
120
121int newsnntp_list_active_times(newsnntp * f, clist ** result);
122void newsnntp_list_active_times_free(clist * l);
123
124/*
125 elements are struct newsnntp_distrib_value_meaning *
126*/
127
128int newsnntp_list_distribution(newsnntp * f, clist ** result);
129void newsnntp_list_distribution_free(clist * l);
130
131/*
132 elements are struct newsnntp_distrib_default_value *
133*/
134
135int newsnntp_list_distrib_pats(newsnntp * f, clist ** result);
136void newsnntp_list_distrib_pats_free(clist * l);
137
138/*
139 elements are struct newsnntp_group_description *
140*/
141
142int newsnntp_list_newsgroups(newsnntp * f, const char * pattern,
143 clist ** result);
144void newsnntp_list_newsgroups_free(clist * l);
145
146/*
147 elements are char *
148*/
149
150int newsnntp_list_subscriptions(newsnntp * f, clist ** result);
151void newsnntp_list_subscriptions_free(clist * l);
152
153/*
154 elements are uint32_t *
155*/
156
157int newsnntp_listgroup(newsnntp * f, const char * group_name,
158 clist ** result);
159void newsnntp_listgroup_free(clist * l);
160
161/*
162 elements are struct newsnntp_xhdr_resp_item *
163*/
164
165int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article,
166 clist ** result);
167int newsnntp_xhdr_range(newsnntp * f, const char * header,
168 uint32_t rangeinf, uint32_t rangesup,
169 clist ** result);
170void newsnntp_xhdr_free(clist * l);
171
172/*
173 elements are struct newsnntp_xover_resp_item *
174*/
175
176int newsnntp_xover_single(newsnntp * f, uint32_t article,
177 struct newsnntp_xover_resp_item ** result);
178int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup,
179 clist ** result);
180void xover_resp_item_free(struct newsnntp_xover_resp_item * n);
181void newsnntp_xover_resp_list_free(clist * l);
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif
diff --git a/libetpan/include/libetpan/newsnntp_socket.h b/libetpan/include/libetpan/newsnntp_socket.h
new file mode 100644
index 0000000..4a52f73
--- a/dev/null
+++ b/libetpan/include/libetpan/newsnntp_socket.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_SOCKET_H
37
38#define NEWSNNTP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46
47#include <libetpan/newsnntp_types.h>
48
49int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/include/libetpan/newsnntp_ssl.h b/libetpan/include/libetpan/newsnntp_ssl.h
new file mode 100644
index 0000000..845484f
--- a/dev/null
+++ b/libetpan/include/libetpan/newsnntp_ssl.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_SSL_H
37
38#define NEWSNNTP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46
47#include <libetpan/newsnntp_types.h>
48
49int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/include/libetpan/newsnntp_types.h b/libetpan/include/libetpan/newsnntp_types.h
new file mode 100644
index 0000000..821df46
--- a/dev/null
+++ b/libetpan/include/libetpan/newsnntp_types.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_TYPES_H
37
38#define NEWSNNTP_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <libetpan/clist.h>
46
47#include <libetpan/mailstream.h>
48#include <libetpan/mmapstring.h>
49
50enum {
51 NEWSNNTP_NO_ERROR = 0,
52 NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME,
53 NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD,
54 NEWSNNTP_ERROR_STREAM,
55 NEWSNNTP_ERROR_UNEXPECTED,
56 NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED,
57 NEWSNNTP_ERROR_NO_ARTICLE_SELECTED,
58 NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER,
59 NEWSNNTP_ERROR_ARTICLE_NOT_FOUND,
60 NEWSNNTP_ERROR_UNEXPECTED_RESPONSE,
61 NEWSNNTP_ERROR_INVALID_RESPONSE,
62 NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP,
63 NEWSNNTP_ERROR_POSTING_NOT_ALLOWED,
64 NEWSNNTP_ERROR_POSTING_FAILED,
65 NEWSNNTP_ERROR_PROGRAM_ERROR,
66 NEWSNNTP_ERROR_NO_PERMISSION,
67 NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD,
68 NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED,
69 NEWSNNTP_ERROR_CONNECTION_REFUSED,
70 NEWSNNTP_ERROR_MEMORY,
71 NEWSNNTP_ERROR_AUTHENTICATION_REJECTED,
72 NEWSNNTP_ERROR_BAD_STATE,
73};
74
75struct newsnntp
76{
77 mailstream * nntp_stream;
78
79 int nntp_readonly;
80
81 uint32_t nntp_progr_rate;
82 progress_function * nntp_progr_fun;
83
84 MMAPString * nntp_stream_buffer;
85 MMAPString * nntp_response_buffer;
86
87 char * nntp_response;
88};
89
90typedef struct newsnntp newsnntp;
91
92struct newsnntp_group_info
93{
94 char * grp_name;
95 uint32_t grp_first;
96 uint32_t grp_last;
97 uint32_t grp_count;
98 char grp_type;
99};
100
101struct newsnntp_group_time {
102 char * grp_name;
103 uint32_t grp_date;
104 char * grp_email;
105};
106
107struct newsnntp_distrib_value_meaning {
108 char * dst_value;
109 char * dst_meaning;
110};
111
112struct newsnntp_distrib_default_value {
113 uint32_t dst_weight;
114 char * dst_group_pattern;
115 char * dst_value;
116};
117
118struct newsnntp_group_description {
119 char * grp_name;
120 char * grp_description;
121};
122
123struct newsnntp_xhdr_resp_item {
124 uint32_t hdr_article;
125 char * hdr_value;
126};
127
128struct newsnntp_xover_resp_item {
129 uint32_t ovr_article;
130 char * ovr_subject;
131 char * ovr_author;
132 char * ovr_date;
133 char * ovr_message_id;
134 char * ovr_references;
135 size_t ovr_size;
136 uint32_t ovr_line_count;
137 clist * ovr_others;
138};
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/include/libetpan/nntpdriver.h b/libetpan/include/libetpan/nntpdriver.h
new file mode 100644
index 0000000..56aaa39
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_H
37
38#define NNTPDRIVER_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/nntpdriver_cached.h b/libetpan/include/libetpan/nntpdriver_cached.h
new file mode 100644
index 0000000..c0264de
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_CACHED_H
37
38#define NNTPDRIVER_CACHED_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/nntpdriver_cached_message.h b/libetpan/include/libetpan/nntpdriver_cached_message.h
new file mode 100644
index 0000000..f515d48
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef NNTPDRIVER_CACHED_MESSAGE_H
39
40#define NNTPDRIVER_CACHED_MESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * nntp_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/nntpdriver_message.h b/libetpan/include/libetpan/nntpdriver_message.h
new file mode 100644
index 0000000..15e80b7
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_MESSAGE_H
37
38#define NNTPDRIVER_MESSAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/nntpdriver_types.h>
45
46extern mailmessage_driver * nntp_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/nntpdriver_types.h b/libetpan/include/libetpan/nntpdriver_types.h
new file mode 100644
index 0000000..7d4b74d
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpdriver_types.h
@@ -0,0 +1,146 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_TYPES_H
37
38#define NNTPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/newsnntp.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* NNTP driver for session */
53
54enum {
55 NNTPDRIVER_SET_MAX_ARTICLES = 1,
56};
57
58struct nntp_session_state_data {
59 newsnntp * nntp_session;
60 char * nntp_userid;
61 char * nntp_password;
62
63 struct newsnntp_group_info * nntp_group_info;
64 char * nntp_group_name;
65
66 clist * nntp_subscribed_list;
67
68 uint32_t nntp_max_articles;
69
70 int nntp_mode_reader;
71};
72
73/* cached NNTP driver for session */
74
75enum {
76 /* the mapping of the parameters should be the same as for nntp */
77 NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
78 /* cache specific */
79 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
80 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
81};
82
83struct nntp_cached_session_state_data {
84 mailsession * nntp_ancestor;
85 char nntp_cache_directory[PATH_MAX];
86 char nntp_flags_directory[PATH_MAX];
87 struct mail_flags_store * nntp_flags_store;
88};
89
90
91/* nntp storage */
92
93/*
94 nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
95
96 - storage this is the storage to initialize.
97
98 - servername this is the name of the NNTP server
99
100 - port is the port to connect to, on the server.
101 you give 0 to use the default port.
102
103 - connection_type is the type of socket layer to use.
104 The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
105
106 - auth_type is the authenticate mechanism to use.
107 The value can be NNTP_AUTH_TYPE_PLAIN.
108
109 - login is the login of the POP3 account.
110
111 - password is the password of the POP3 account.
112
113 - cached if this value is != 0, a persistant cache will be
114 stored on local system.
115
116 - cache_directory is the location of the cache
117
118 - flags_directory is the location of the flags
119*/
120
121struct nntp_mailstorage {
122 char * nntp_servername;
123 uint16_t nntp_port;
124 char * nntp_command;
125 int nntp_connection_type;
126
127 int nntp_auth_type;
128 char * nntp_login;
129 char * nntp_password;
130
131 int nntp_cached;
132 char * nntp_cache_directory;
133 char * nntp_flags_directory;
134};
135
136/* this is the type of NNTP authentication */
137
138enum {
139 NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
140};
141
142#ifdef __cplusplus
143}
144#endif
145
146#endif
diff --git a/libetpan/include/libetpan/nntpstorage.h b/libetpan/include/libetpan/nntpstorage.h
new file mode 100644
index 0000000..7b046f4
--- a/dev/null
+++ b/libetpan/include/libetpan/nntpstorage.h
@@ -0,0 +1,93 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPSTORAGE_H
37
38#define NNTPSTORAGE_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46
47/*
48 nntp_mailstorage_init is the constructor for a NNTP storage
49
50 @param storage this is the storage to initialize.
51
52 @param servername this is the name of the NNTP server
53
54 @param port is the port to connect to, on the server.
55 you give 0 to use the default port.
56
57 @param command the command used to connect to the server instead of
58 allowing normal TCP connections to be used.
59
60 @param connection_type is the type of socket layer to use.
61 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
62 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
63 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
64 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
65
66 @param auth_type is the authenticate mechanism to use.
67 The value can be NNTP_AUTH_TYPE_PLAIN.
68
69 @param login is the login of the POP3 account.
70
71 @param password is the password of the POP3 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77
78 @param flags_directory is the location of the flags
79*/
80
81int nntp_mailstorage_init(struct mailstorage * storage,
82 char * nntp_servername, uint16_t nntp_port,
83 char * nntp_command,
84 int nntp_connection_type, int nntp_auth_type,
85 char * nntp_login, char * nntp_password,
86 int nntp_cached, char * nntp_cache_directory,
87 char * nntp_flags_directory);
88
89#ifdef __cplusplus
90}
91#endif
92
93#endif
diff --git a/libetpan/include/libetpan/pop3driver.h b/libetpan/include/libetpan/pop3driver.h
new file mode 100644
index 0000000..b70f69e
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3driver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_H
37
38#define POP3DRIVER_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * pop3_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/pop3driver_cached.h b/libetpan/include/libetpan/pop3driver_cached.h
new file mode 100644
index 0000000..4f4b6c9
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3driver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_H
37
38#define POP3DRIVER_CACHED_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45
46extern mailsession_driver * pop3_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/pop3driver_cached_message.h b/libetpan/include/libetpan/pop3driver_cached_message.h
new file mode 100644
index 0000000..f13cec7
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3driver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_MESSAGE_H
37
38#define POP3DRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/pop3driver_message.h b/libetpan/include/libetpan/pop3driver_message.h
new file mode 100644
index 0000000..ad0a01b
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3driver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_MESSAGE_H
37
38#define POP3DRIVER_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/include/libetpan/pop3driver_types.h b/libetpan/include/libetpan/pop3driver_types.h
new file mode 100644
index 0000000..4bb872c
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3driver_types.h
@@ -0,0 +1,153 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_TYPES_H
37
38#define POP3DRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailpop3.h>
44#include <libetpan/maildriver_types.h>
45#include <libetpan/chash.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* POP3 driver for session */
53
54enum {
55 POP3DRIVER_SET_AUTH_TYPE = 1,
56};
57
58enum {
59 POP3DRIVER_AUTH_TYPE_PLAIN = 0,
60 POP3DRIVER_AUTH_TYPE_APOP,
61 POP3DRIVER_AUTH_TYPE_TRY_APOP,
62};
63
64struct pop3_session_state_data {
65 int pop3_auth_type;
66 mailpop3 * pop3_session;
67};
68
69/* cached POP3 driver for session */
70
71enum {
72 /* the mapping of the parameters should be the same as for pop3 */
73 POP3DRIVER_CACHED_SET_AUTH_TYPE = 1,
74 /* cache specific */
75 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
76 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
77};
78
79struct pop3_cached_session_state_data {
80 mailsession * pop3_ancestor;
81 char pop3_cache_directory[PATH_MAX];
82 char pop3_flags_directory[PATH_MAX];
83 chash * pop3_flags_hash;
84 carray * pop3_flags_array;
85 struct mail_flags_store * pop3_flags_store;
86};
87
88/* pop3 storage */
89
90/*
91 pop3_mailstorage is the state data specific to the POP3 storage.
92
93 - servername this is the name of the POP3 server
94
95 - port is the port to connect to, on the server.
96 you give 0 to use the default port.
97
98 - connection_type is the type of socket layer to use.
99 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
100 CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS.
101
102 - auth_type is the authenticate mechanism to use.
103 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
104 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
105
106 - login is the login of the POP3 account.
107
108 - password is the password of the POP3 account.
109
110 - cached if this value is != 0, a persistant cache will be
111 stored on local system.
112
113 - cache_directory is the location of the cache.
114
115 - flags_directory is the location of the flags.
116*/
117
118struct pop3_mailstorage {
119 char * pop3_servername;
120 uint16_t pop3_port;
121 char * pop3_command;
122 int pop3_connection_type;
123
124 int pop3_auth_type;
125 char * pop3_login;
126 char * pop3_password;
127
128 int pop3_cached;
129 char * pop3_cache_directory;
130 char * pop3_flags_directory;
131};
132
133/* this is the type of POP3 authentication */
134
135enum {
136 POP3_AUTH_TYPE_PLAIN, /* plain text authentication */
137 POP3_AUTH_TYPE_APOP, /* APOP authentication */
138 POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails,
139 try plain text */
140 POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
141 POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
142 POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
143 POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
144 POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
145 POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
146 POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
147};
148
149#ifdef __cplusplus
150}
151#endif
152
153#endif
diff --git a/libetpan/include/libetpan/pop3storage.h b/libetpan/include/libetpan/pop3storage.h
new file mode 100644
index 0000000..e8cd513
--- a/dev/null
+++ b/libetpan/include/libetpan/pop3storage.h
@@ -0,0 +1,95 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3STORAGE_H
37
38#define POP3STORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45#include <libetpan/pop3driver.h>
46#include <libetpan/pop3driver_cached.h>
47
48/*
49 pop3_mailstorage_init is the constructor for a POP3 storage
50
51 @param storage this is the storage to initialize.
52
53 @param servername this is the name of the POP3 server
54
55 @param port is the port to connect to, on the server.
56 you give 0 to use the default port.
57
58 @param command the command used to connect to the server instead of
59 allowing normal TCP connections to be used.
60
61 @param connection_type is the type of socket layer to use.
62 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
63 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
64 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
65 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
66
67 @param auth_type is the authenticate mechanism to use.
68 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
69 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
70
71 @param login is the login of the POP3 account.
72
73 @param password is the password of the POP3 account.
74
75 @param cached if this value is != 0, a persistant cache will be
76 stored on local system.
77
78 @param cache_directory is the location of the cache
79
80 @param flags_directory is the location of the flags
81*/
82
83int pop3_mailstorage_init(struct mailstorage * storage,
84 char * pop3_servername, uint16_t pop3_port,
85 char * pop3_command,
86 int pop3_connection_type, int pop3_auth_type,
87 char * pop3_login, char * pop3_password,
88 int pop3_cached, char * pop3_cache_directory,
89 char * pop3_flags_directory);
90
91#ifdef __cplusplus
92}
93#endif
94
95#endif
diff --git a/libetpan/libetpan-config.h b/libetpan/libetpan-config.h
new file mode 100644
index 0000000..20d1e62
--- a/dev/null
+++ b/libetpan/libetpan-config.h
@@ -0,0 +1,7 @@
1#ifndef LIBETPAN_CONFIG_H
2#define LIBETPAN_CONFIG_H
3#include <limits.h>
4#include <sys/param.h>
5#define MAIL_DIR_SEPARATOR '/'
6#define MAIL_DIR_SEPARATOR_S "/"
7#endif
diff --git a/libetpan/libetpan.pro b/libetpan/libetpan.pro
new file mode 100644
index 0000000..10f51da
--- a/dev/null
+++ b/libetpan/libetpan.pro
@@ -0,0 +1,450 @@
1######################################################################
2# Automatically generated by qmake (1.07a) Fri Mar 18 19:27:39 2005
3######################################################################
4
5TEMPLATE = lib
6 TARGET = microlibetpan
7OBJECTS_DIR = obj
8MOC_DIR = moc
9DESTDIR=../bin
10DEPENDPATH += include/libetpan \
11 src/data-types \
12 src/engine \
13 src/main \
14 src/driver/interface \
15 src/driver/tools \
16 src/low-level/imap \
17 src/low-level/imf \
18 src/low-level/maildir \
19 src/low-level/mbox \
20 src/low-level/mh \
21 src/low-level/mime \
22 src/low-level/nntp \
23 src/low-level/pop3 \
24 src/low-level/smtp \
25 src/driver/implementation/data-message \
26 src/driver/implementation/db \
27 src/driver/implementation/hotmail \
28 src/driver/implementation/imap \
29 src/driver/implementation/maildir \
30 src/driver/implementation/mbox \
31 src/driver/implementation/mh \
32 src/driver/implementation/mime-message \
33 src/driver/implementation/nntp \
34 src/driver/implementation/pop3
35INCLUDEPATH += . \
36 ./include \
37 src/data-types \
38 src/engine \
39 include/libetpan \
40 src/main \
41 src/driver/interface \
42 src/driver/tools \
43 src/low-level/imap \
44 src/low-level/imf \
45 src/low-level/maildir \
46 src/low-level/mbox \
47 src/low-level/mh \
48 src/low-level/mime \
49 src/low-level/nntp \
50 src/low-level/pop3 \
51 src/low-level/smtp \
52 src/driver/implementation/data-message \
53 src/driver/implementation/db \
54 src/driver/implementation/hotmail \
55 src/driver/implementation/imap \
56 src/driver/implementation/maildir \
57 src/driver/implementation/mbox \
58 src/driver/implementation/mh \
59 src/driver/implementation/mime-message \
60 src/driver/implementation/nntp \
61 src/driver/implementation/pop3
62
63# Input
64HEADERS += config.h \
65 libetpan-config.h \
66 include/libetpan/carray.h \
67 include/libetpan/charconv.h \
68 include/libetpan/chash.h \
69 include/libetpan/cinthash.h \
70 include/libetpan/clist.h \
71 include/libetpan/data_message_driver.h \
72 include/libetpan/dbdriver.h \
73 include/libetpan/dbdriver_message.h \
74 include/libetpan/dbdriver_types.h \
75 include/libetpan/dbstorage.h \
76 include/libetpan/generic_cache_types.h \
77 include/libetpan/hotmailstorage.h \
78 include/libetpan/imapdriver.h \
79 include/libetpan/imapdriver_cached.h \
80 include/libetpan/imapdriver_cached_message.h \
81 include/libetpan/imapdriver_message.h \
82 include/libetpan/imapdriver_types.h \
83 include/libetpan/imapstorage.h \
84 include/libetpan/libetpan-config.h \
85 include/libetpan/libetpan.h \
86 include/libetpan/libetpan_version.h \
87 include/libetpan/mail.h \
88 include/libetpan/maildir.h \
89 include/libetpan/maildir_types.h \
90 include/libetpan/maildirdriver.h \
91 include/libetpan/maildirdriver_cached.h \
92 include/libetpan/maildirdriver_cached_message.h \
93 include/libetpan/maildirdriver_message.h \
94 include/libetpan/maildirdriver_types.h \
95 include/libetpan/maildirstorage.h \
96 include/libetpan/maildriver.h \
97 include/libetpan/maildriver_errors.h \
98 include/libetpan/maildriver_types.h \
99 include/libetpan/maildriver_types_helper.h \
100 include/libetpan/mailengine.h \
101 include/libetpan/mailfolder.h \
102 include/libetpan/mailimap.h \
103 include/libetpan/mailimap_helper.h \
104 include/libetpan/mailimap_socket.h \
105 include/libetpan/mailimap_ssl.h \
106 include/libetpan/mailimap_types.h \
107 include/libetpan/mailimap_types_helper.h \
108 include/libetpan/mailimf.h \
109 include/libetpan/mailimf_types.h \
110 include/libetpan/mailimf_types_helper.h \
111 include/libetpan/mailimf_write_file.h \
112 include/libetpan/mailimf_write_generic.h \
113 include/libetpan/mailimf_write_mem.h \
114 include/libetpan/mailmbox.h \
115 include/libetpan/mailmbox_types.h \
116 include/libetpan/mailmessage.h \
117 include/libetpan/mailmessage_types.h \
118 include/libetpan/mailmh.h \
119 include/libetpan/mailmime.h \
120 include/libetpan/mailmime_content.h \
121 include/libetpan/mailmime_decode.h \
122 include/libetpan/mailmime_disposition.h \
123 include/libetpan/mailmime_types.h \
124 include/libetpan/mailmime_types_helper.h \
125 include/libetpan/mailmime_write_file.h \
126 include/libetpan/mailmime_write_generic.h \
127 include/libetpan/mailmime_write_mem.h \
128 include/libetpan/mailpop3.h \
129 include/libetpan/mailpop3_helper.h \
130 include/libetpan/mailpop3_socket.h \
131 include/libetpan/mailpop3_ssl.h \
132 include/libetpan/mailpop3_types.h \
133 include/libetpan/mailprivacy.h \
134 include/libetpan/mailprivacy_gnupg.h \
135 include/libetpan/mailprivacy_smime.h \
136 include/libetpan/mailprivacy_tools.h \
137 include/libetpan/mailprivacy_types.h \
138 include/libetpan/mailsem.h \
139 include/libetpan/mailsmtp.h \
140 include/libetpan/mailsmtp_helper.h \
141 include/libetpan/mailsmtp_socket.h \
142 include/libetpan/mailsmtp_ssl.h \
143 include/libetpan/mailsmtp_types.h \
144 include/libetpan/mailstorage.h \
145 include/libetpan/mailstorage_types.h \
146 include/libetpan/mailstream.h \
147 include/libetpan/mailstream_helper.h \
148 include/libetpan/mailstream_low.h \
149 include/libetpan/mailstream_socket.h \
150 include/libetpan/mailstream_ssl.h \
151 include/libetpan/mailstream_types.h \
152 include/libetpan/mailthread.h \
153 include/libetpan/mailthread_types.h \
154 include/libetpan/mboxdriver.h \
155 include/libetpan/mboxdriver_cached.h \
156 include/libetpan/mboxdriver_cached_message.h \
157 include/libetpan/mboxdriver_message.h \
158 include/libetpan/mboxdriver_types.h \
159 include/libetpan/mboxstorage.h \
160 include/libetpan/mhdriver.h \
161 include/libetpan/mhdriver_cached.h \
162 include/libetpan/mhdriver_cached_message.h \
163 include/libetpan/mhdriver_message.h \
164 include/libetpan/mhdriver_types.h \
165 include/libetpan/mhstorage.h \
166 include/libetpan/mime_message_driver.h \
167 include/libetpan/mmapstring.h \
168 include/libetpan/newsnntp.h \
169 include/libetpan/newsnntp_socket.h \
170 include/libetpan/newsnntp_ssl.h \
171 include/libetpan/newsnntp_types.h \
172 include/libetpan/nntpdriver.h \
173 include/libetpan/nntpdriver_cached.h \
174 include/libetpan/nntpdriver_cached_message.h \
175 include/libetpan/nntpdriver_message.h \
176 include/libetpan/nntpdriver_types.h \
177 include/libetpan/nntpstorage.h \
178 include/libetpan/pop3driver.h \
179 include/libetpan/pop3driver_cached.h \
180 include/libetpan/pop3driver_cached_message.h \
181 include/libetpan/pop3driver_message.h \
182 include/libetpan/pop3driver_types.h \
183 include/libetpan/pop3storage.h \
184 src/data-types/base64.h \
185 src/data-types/carray.h \
186 src/data-types/charconv.h \
187 src/data-types/chash.h \
188 src/data-types/cinthash.h \
189 src/data-types/clist.h \
190 src/data-types/connect.h \
191 src/data-types/hmac-md5.h \
192 src/data-types/mail.h \
193 src/data-types/mail_cache_db.h \
194 src/data-types/mail_cache_db_types.h \
195 src/data-types/maillock.h \
196 src/data-types/mailsem.h \
197 src/data-types/mailstream.h \
198 src/data-types/mailstream_helper.h \
199 src/data-types/mailstream_low.h \
200 src/data-types/mailstream_socket.h \
201 src/data-types/mailstream_ssl.h \
202 src/data-types/mailstream_types.h \
203 src/data-types/mapping.h \
204 src/data-types/md5.h \
205 src/data-types/md5global.h \
206 src/data-types/mmapstring.h \
207 src/engine/mailengine.h \
208 src/engine/mailprivacy.h \
209 src/engine/mailprivacy_gnupg.h \
210 src/engine/mailprivacy_smime.h \
211 src/engine/mailprivacy_tools.h \
212 src/engine/mailprivacy_types.h \
213 src/main/libetpan.h \
214 src/main/libetpan_version.h \
215 src/driver/interface/maildriver.h \
216 src/driver/interface/maildriver_errors.h \
217 src/driver/interface/maildriver_tools.h \
218 src/driver/interface/maildriver_types.h \
219 src/driver/interface/maildriver_types_helper.h \
220 src/driver/interface/mailfolder.h \
221 src/driver/interface/mailmessage.h \
222 src/driver/interface/mailmessage_tools.h \
223 src/driver/interface/mailmessage_types.h \
224 src/driver/interface/mailstorage.h \
225 src/driver/interface/mailstorage_tools.h \
226 src/driver/interface/mailstorage_types.h \
227 src/driver/tools/generic_cache.h \
228 src/driver/tools/generic_cache_types.h \
229 src/driver/tools/imfcache.h \
230 src/driver/tools/mailthread.h \
231 src/driver/tools/mailthread_types.h \
232 src/low-level/imap/mailimap.h \
233 src/low-level/imap/mailimap_helper.h \
234 src/low-level/imap/mailimap_keywords.h \
235 src/low-level/imap/mailimap_parser.h \
236 src/low-level/imap/mailimap_print.h \
237 src/low-level/imap/mailimap_sender.h \
238 src/low-level/imap/mailimap_socket.h \
239 src/low-level/imap/mailimap_ssl.h \
240 src/low-level/imap/mailimap_types.h \
241 src/low-level/imap/mailimap_types_helper.h \
242 src/low-level/imf/mailimf.h \
243 src/low-level/imf/mailimf_types.h \
244 src/low-level/imf/mailimf_types_helper.h \
245 src/low-level/imf/mailimf_write.h \
246 src/low-level/imf/mailimf_write_file.h \
247 src/low-level/imf/mailimf_write_generic.h \
248 src/low-level/imf/mailimf_write_mem.h \
249 src/low-level/maildir/maildir.h \
250 src/low-level/maildir/maildir_types.h \
251 src/low-level/mbox/mailmbox.h \
252 src/low-level/mbox/mailmbox_parse.h \
253 src/low-level/mbox/mailmbox_types.h \
254 src/low-level/mh/mailmh.h \
255 src/low-level/mime/mailmime.h \
256 src/low-level/mime/mailmime_content.h \
257 src/low-level/mime/mailmime_decode.h \
258 src/low-level/mime/mailmime_disposition.h \
259 src/low-level/mime/mailmime_types.h \
260 src/low-level/mime/mailmime_types_helper.h \
261 src/low-level/mime/mailmime_write.h \
262 src/low-level/mime/mailmime_write_file.h \
263 src/low-level/mime/mailmime_write_generic.h \
264 src/low-level/mime/mailmime_write_mem.h \
265 src/low-level/nntp/newsnntp.h \
266 src/low-level/nntp/newsnntp_socket.h \
267 src/low-level/nntp/newsnntp_ssl.h \
268 src/low-level/nntp/newsnntp_types.h \
269 src/low-level/pop3/mailpop3.h \
270 src/low-level/pop3/mailpop3_helper.h \
271 src/low-level/pop3/mailpop3_socket.h \
272 src/low-level/pop3/mailpop3_ssl.h \
273 src/low-level/pop3/mailpop3_types.h \
274 src/low-level/smtp/mailsmtp.h \
275 src/low-level/smtp/mailsmtp_helper.h \
276 src/low-level/smtp/mailsmtp_socket.h \
277 src/low-level/smtp/mailsmtp_ssl.h \
278 src/low-level/smtp/mailsmtp_types.h \
279 src/driver/implementation/data-message/data_message_driver.h \
280 src/driver/implementation/db/dbdriver.h \
281 src/driver/implementation/db/dbdriver_message.h \
282 src/driver/implementation/db/dbdriver_types.h \
283 src/driver/implementation/db/dbstorage.h \
284 src/driver/implementation/hotmail/hotmailstorage.h \
285 src/driver/implementation/imap/imapdriver.h \
286 src/driver/implementation/imap/imapdriver_cached.h \
287 src/driver/implementation/imap/imapdriver_cached_message.h \
288 src/driver/implementation/imap/imapdriver_message.h \
289 src/driver/implementation/imap/imapdriver_tools.h \
290 src/driver/implementation/imap/imapdriver_types.h \
291 src/driver/implementation/imap/imapstorage.h \
292 src/driver/implementation/maildir/maildirdriver.h \
293 src/driver/implementation/maildir/maildirdriver_cached.h \
294 src/driver/implementation/maildir/maildirdriver_cached_message.h \
295 src/driver/implementation/maildir/maildirdriver_message.h \
296 src/driver/implementation/maildir/maildirdriver_tools.h \
297 src/driver/implementation/maildir/maildirdriver_types.h \
298 src/driver/implementation/maildir/maildirstorage.h \
299 src/driver/implementation/mbox/mboxdriver.h \
300 src/driver/implementation/mbox/mboxdriver_cached.h \
301 src/driver/implementation/mbox/mboxdriver_cached_message.h \
302 src/driver/implementation/mbox/mboxdriver_message.h \
303 src/driver/implementation/mbox/mboxdriver_tools.h \
304 src/driver/implementation/mbox/mboxdriver_types.h \
305 src/driver/implementation/mbox/mboxstorage.h \
306 src/driver/implementation/mh/mhdriver.h \
307 src/driver/implementation/mh/mhdriver_cached.h \
308 src/driver/implementation/mh/mhdriver_cached_message.h \
309 src/driver/implementation/mh/mhdriver_message.h \
310 src/driver/implementation/mh/mhdriver_tools.h \
311 src/driver/implementation/mh/mhdriver_types.h \
312 src/driver/implementation/mh/mhstorage.h \
313 src/driver/implementation/mime-message/mime_message_driver.h \
314 src/driver/implementation/nntp/nntpdriver.h \
315 src/driver/implementation/nntp/nntpdriver_cached.h \
316 src/driver/implementation/nntp/nntpdriver_cached_message.h \
317 src/driver/implementation/nntp/nntpdriver_message.h \
318 src/driver/implementation/nntp/nntpdriver_tools.h \
319 src/driver/implementation/nntp/nntpdriver_types.h \
320 src/driver/implementation/nntp/nntpstorage.h \
321 src/driver/implementation/pop3/pop3driver.h \
322 src/driver/implementation/pop3/pop3driver_cached.h \
323 src/driver/implementation/pop3/pop3driver_cached_message.h \
324 src/driver/implementation/pop3/pop3driver_message.h \
325 src/driver/implementation/pop3/pop3driver_tools.h \
326 src/driver/implementation/pop3/pop3driver_types.h \
327 src/driver/implementation/pop3/pop3storage.h
328SOURCES += src/data-types/base64.c \
329 src/data-types/carray.c \
330 src/data-types/charconv.c \
331 src/data-types/chash.c \
332 src/data-types/cinthash.c \
333 src/data-types/clist.c \
334 src/data-types/connect.c \
335 src/data-types/mail_cache_db.c \
336 src/data-types/maillock.c \
337 src/data-types/mailsem.c \
338 src/data-types/mailstream.c \
339 src/data-types/mailstream_helper.c \
340 src/data-types/mailstream_low.c \
341 src/data-types/mailstream_socket.c \
342 src/data-types/mailstream_ssl.c \
343 src/data-types/mapping.c \
344 src/data-types/md5.c \
345 src/data-types/mmapstring.c \
346 src/engine/mailengine.c \
347 src/engine/mailprivacy.c \
348 src/engine/mailprivacy_gnupg.c \
349 src/engine/mailprivacy_smime.c \
350 src/engine/mailprivacy_tools.c \
351 src/main/libetpan_version.c \
352 src/driver/interface/maildriver.c \
353 src/driver/interface/maildriver_tools.c \
354 src/driver/interface/maildriver_types.c \
355 src/driver/interface/maildriver_types_helper.c \
356 src/driver/interface/mailfolder.c \
357 src/driver/interface/mailmessage.c \
358 src/driver/interface/mailmessage_tools.c \
359 src/driver/interface/mailmessage_types.c \
360 src/driver/interface/mailstorage.c \
361 src/driver/interface/mailstorage_tools.c \
362 src/driver/tools/generic_cache.c \
363 src/driver/tools/imfcache.c \
364 src/driver/tools/mailthread.c \
365 src/driver/tools/mailthread_types.c \
366 src/low-level/imap/mailimap.c \
367 src/low-level/imap/mailimap_helper.c \
368 src/low-level/imap/mailimap_keywords.c \
369 src/low-level/imap/mailimap_parser.c \
370 src/low-level/imap/mailimap_print.c \
371 src/low-level/imap/mailimap_sender.c \
372 src/low-level/imap/mailimap_socket.c \
373 src/low-level/imap/mailimap_ssl.c \
374 src/low-level/imap/mailimap_types.c \
375 src/low-level/imap/mailimap_types_helper.c \
376 src/low-level/imf/mailimf.c \
377 src/low-level/imf/mailimf_types.c \
378 src/low-level/imf/mailimf_types_helper.c \
379 src/low-level/imf/mailimf_write.c \
380 src/low-level/imf/mailimf_write_file.c \
381 src/low-level/imf/mailimf_write_generic.c \
382 src/low-level/imf/mailimf_write_mem.c \
383 src/low-level/maildir/maildir.c \
384 src/low-level/mbox/mailmbox.c \
385 src/low-level/mbox/mailmbox_parse.c \
386 src/low-level/mbox/mailmbox_types.c \
387 src/low-level/mh/mailmh.c \
388 src/low-level/mime/mailmime.c \
389 src/low-level/mime/mailmime_content.c \
390 src/low-level/mime/mailmime_decode.c \
391 src/low-level/mime/mailmime_disposition.c \
392 src/low-level/mime/mailmime_types.c \
393 src/low-level/mime/mailmime_types_helper.c \
394 src/low-level/mime/mailmime_write.c \
395 src/low-level/mime/mailmime_write_file.c \
396 src/low-level/mime/mailmime_write_generic.c \
397 src/low-level/mime/mailmime_write_mem.c \
398 src/low-level/nntp/newsnntp.c \
399 src/low-level/nntp/newsnntp_socket.c \
400 src/low-level/nntp/newsnntp_ssl.c \
401 src/low-level/pop3/mailpop3.c \
402 src/low-level/pop3/mailpop3_helper.c \
403 src/low-level/pop3/mailpop3_socket.c \
404 src/low-level/pop3/mailpop3_ssl.c \
405 src/low-level/smtp/mailsmtp.c \
406 src/low-level/smtp/mailsmtp_helper.c \
407 src/low-level/smtp/mailsmtp_socket.c \
408 src/low-level/smtp/mailsmtp_ssl.c \
409 src/driver/implementation/data-message/data_message_driver.c \
410 src/driver/implementation/db/dbdriver.c \
411 src/driver/implementation/db/dbdriver_message.c \
412 src/driver/implementation/db/dbstorage.c \
413 src/driver/implementation/hotmail/hotmailstorage.c \
414 src/driver/implementation/imap/imapdriver.c \
415 src/driver/implementation/imap/imapdriver_cached.c \
416 src/driver/implementation/imap/imapdriver_cached_message.c \
417 src/driver/implementation/imap/imapdriver_message.c \
418 src/driver/implementation/imap/imapdriver_tools.c \
419 src/driver/implementation/imap/imapstorage.c \
420 src/driver/implementation/maildir/maildirdriver.c \
421 src/driver/implementation/maildir/maildirdriver_cached.c \
422 src/driver/implementation/maildir/maildirdriver_cached_message.c \
423 src/driver/implementation/maildir/maildirdriver_message.c \
424 src/driver/implementation/maildir/maildirdriver_tools.c \
425 src/driver/implementation/maildir/maildirstorage.c \
426 src/driver/implementation/mbox/mboxdriver.c \
427 src/driver/implementation/mbox/mboxdriver_cached.c \
428 src/driver/implementation/mbox/mboxdriver_cached_message.c \
429 src/driver/implementation/mbox/mboxdriver_message.c \
430 src/driver/implementation/mbox/mboxdriver_tools.c \
431 src/driver/implementation/mbox/mboxstorage.c \
432 src/driver/implementation/mh/mhdriver.c \
433 src/driver/implementation/mh/mhdriver_cached.c \
434 src/driver/implementation/mh/mhdriver_cached_message.c \
435 src/driver/implementation/mh/mhdriver_message.c \
436 src/driver/implementation/mh/mhdriver_tools.c \
437 src/driver/implementation/mh/mhstorage.c \
438 src/driver/implementation/mime-message/mime_message_driver.c \
439 src/driver/implementation/nntp/nntpdriver.c \
440 src/driver/implementation/nntp/nntpdriver_cached.c \
441 src/driver/implementation/nntp/nntpdriver_cached_message.c \
442 src/driver/implementation/nntp/nntpdriver_message.c \
443 src/driver/implementation/nntp/nntpdriver_tools.c \
444 src/driver/implementation/nntp/nntpstorage.c \
445 src/driver/implementation/pop3/pop3driver.c \
446 src/driver/implementation/pop3/pop3driver_cached.c \
447 src/driver/implementation/pop3/pop3driver_cached_message.c \
448 src/driver/implementation/pop3/pop3driver_message.c \
449 src/driver/implementation/pop3/pop3driver_tools.c \
450 src/driver/implementation/pop3/pop3storage.c
diff --git a/libetpan/libetpanE.pro b/libetpan/libetpanE.pro
new file mode 100644
index 0000000..4b82196
--- a/dev/null
+++ b/libetpan/libetpanE.pro
@@ -0,0 +1,450 @@
1######################################################################
2# Automatically generated by qmake (1.07a) Fri Mar 18 19:27:39 2005
3######################################################################
4
5TEMPLATE = lib
6 TARGET = microlibetpan
7OBJECTS_DIR = obj/$(PLATFORM)
8MOC_DIR = moc/$(PLATFORM)
9DESTDIR=$(QPEDIR)/lib
10DEPENDPATH += include/libetpan \
11 src/data-types \
12 src/engine \
13 src/main \
14 src/driver/interface \
15 src/driver/tools \
16 src/low-level/imap \
17 src/low-level/imf \
18 src/low-level/maildir \
19 src/low-level/mbox \
20 src/low-level/mh \
21 src/low-level/mime \
22 src/low-level/nntp \
23 src/low-level/pop3 \
24 src/low-level/smtp \
25 src/driver/implementation/data-message \
26 src/driver/implementation/db \
27 src/driver/implementation/hotmail \
28 src/driver/implementation/imap \
29 src/driver/implementation/maildir \
30 src/driver/implementation/mbox \
31 src/driver/implementation/mh \
32 src/driver/implementation/mime-message \
33 src/driver/implementation/nntp \
34 src/driver/implementation/pop3
35INCLUDEPATH += . \
36 ./include \
37 src/data-types \
38 src/engine \
39 include/libetpan \
40 src/main \
41 src/driver/interface \
42 src/driver/tools \
43 src/low-level/imap \
44 src/low-level/imf \
45 src/low-level/maildir \
46 src/low-level/mbox \
47 src/low-level/mh \
48 src/low-level/mime \
49 src/low-level/nntp \
50 src/low-level/pop3 \
51 src/low-level/smtp \
52 src/driver/implementation/data-message \
53 src/driver/implementation/db \
54 src/driver/implementation/hotmail \
55 src/driver/implementation/imap \
56 src/driver/implementation/maildir \
57 src/driver/implementation/mbox \
58 src/driver/implementation/mh \
59 src/driver/implementation/mime-message \
60 src/driver/implementation/nntp \
61 src/driver/implementation/pop3
62
63# Input
64HEADERS += config.h \
65 libetpan-config.h \
66 include/libetpan/carray.h \
67 include/libetpan/charconv.h \
68 include/libetpan/chash.h \
69 include/libetpan/cinthash.h \
70 include/libetpan/clist.h \
71 include/libetpan/data_message_driver.h \
72 include/libetpan/dbdriver.h \
73 include/libetpan/dbdriver_message.h \
74 include/libetpan/dbdriver_types.h \
75 include/libetpan/dbstorage.h \
76 include/libetpan/generic_cache_types.h \
77 include/libetpan/hotmailstorage.h \
78 include/libetpan/imapdriver.h \
79 include/libetpan/imapdriver_cached.h \
80 include/libetpan/imapdriver_cached_message.h \
81 include/libetpan/imapdriver_message.h \
82 include/libetpan/imapdriver_types.h \
83 include/libetpan/imapstorage.h \
84 include/libetpan/libetpan-config.h \
85 include/libetpan/libetpan.h \
86 include/libetpan/libetpan_version.h \
87 include/libetpan/mail.h \
88 include/libetpan/maildir.h \
89 include/libetpan/maildir_types.h \
90 include/libetpan/maildirdriver.h \
91 include/libetpan/maildirdriver_cached.h \
92 include/libetpan/maildirdriver_cached_message.h \
93 include/libetpan/maildirdriver_message.h \
94 include/libetpan/maildirdriver_types.h \
95 include/libetpan/maildirstorage.h \
96 include/libetpan/maildriver.h \
97 include/libetpan/maildriver_errors.h \
98 include/libetpan/maildriver_types.h \
99 include/libetpan/maildriver_types_helper.h \
100 include/libetpan/mailengine.h \
101 include/libetpan/mailfolder.h \
102 include/libetpan/mailimap.h \
103 include/libetpan/mailimap_helper.h \
104 include/libetpan/mailimap_socket.h \
105 include/libetpan/mailimap_ssl.h \
106 include/libetpan/mailimap_types.h \
107 include/libetpan/mailimap_types_helper.h \
108 include/libetpan/mailimf.h \
109 include/libetpan/mailimf_types.h \
110 include/libetpan/mailimf_types_helper.h \
111 include/libetpan/mailimf_write_file.h \
112 include/libetpan/mailimf_write_generic.h \
113 include/libetpan/mailimf_write_mem.h \
114 include/libetpan/mailmbox.h \
115 include/libetpan/mailmbox_types.h \
116 include/libetpan/mailmessage.h \
117 include/libetpan/mailmessage_types.h \
118 include/libetpan/mailmh.h \
119 include/libetpan/mailmime.h \
120 include/libetpan/mailmime_content.h \
121 include/libetpan/mailmime_decode.h \
122 include/libetpan/mailmime_disposition.h \
123 include/libetpan/mailmime_types.h \
124 include/libetpan/mailmime_types_helper.h \
125 include/libetpan/mailmime_write_file.h \
126 include/libetpan/mailmime_write_generic.h \
127 include/libetpan/mailmime_write_mem.h \
128 include/libetpan/mailpop3.h \
129 include/libetpan/mailpop3_helper.h \
130 include/libetpan/mailpop3_socket.h \
131 include/libetpan/mailpop3_ssl.h \
132 include/libetpan/mailpop3_types.h \
133 include/libetpan/mailprivacy.h \
134 include/libetpan/mailprivacy_gnupg.h \
135 include/libetpan/mailprivacy_smime.h \
136 include/libetpan/mailprivacy_tools.h \
137 include/libetpan/mailprivacy_types.h \
138 include/libetpan/mailsem.h \
139 include/libetpan/mailsmtp.h \
140 include/libetpan/mailsmtp_helper.h \
141 include/libetpan/mailsmtp_socket.h \
142 include/libetpan/mailsmtp_ssl.h \
143 include/libetpan/mailsmtp_types.h \
144 include/libetpan/mailstorage.h \
145 include/libetpan/mailstorage_types.h \
146 include/libetpan/mailstream.h \
147 include/libetpan/mailstream_helper.h \
148 include/libetpan/mailstream_low.h \
149 include/libetpan/mailstream_socket.h \
150 include/libetpan/mailstream_ssl.h \
151 include/libetpan/mailstream_types.h \
152 include/libetpan/mailthread.h \
153 include/libetpan/mailthread_types.h \
154 include/libetpan/mboxdriver.h \
155 include/libetpan/mboxdriver_cached.h \
156 include/libetpan/mboxdriver_cached_message.h \
157 include/libetpan/mboxdriver_message.h \
158 include/libetpan/mboxdriver_types.h \
159 include/libetpan/mboxstorage.h \
160 include/libetpan/mhdriver.h \
161 include/libetpan/mhdriver_cached.h \
162 include/libetpan/mhdriver_cached_message.h \
163 include/libetpan/mhdriver_message.h \
164 include/libetpan/mhdriver_types.h \
165 include/libetpan/mhstorage.h \
166 include/libetpan/mime_message_driver.h \
167 include/libetpan/mmapstring.h \
168 include/libetpan/newsnntp.h \
169 include/libetpan/newsnntp_socket.h \
170 include/libetpan/newsnntp_ssl.h \
171 include/libetpan/newsnntp_types.h \
172 include/libetpan/nntpdriver.h \
173 include/libetpan/nntpdriver_cached.h \
174 include/libetpan/nntpdriver_cached_message.h \
175 include/libetpan/nntpdriver_message.h \
176 include/libetpan/nntpdriver_types.h \
177 include/libetpan/nntpstorage.h \
178 include/libetpan/pop3driver.h \
179 include/libetpan/pop3driver_cached.h \
180 include/libetpan/pop3driver_cached_message.h \
181 include/libetpan/pop3driver_message.h \
182 include/libetpan/pop3driver_types.h \
183 include/libetpan/pop3storage.h \
184 src/data-types/base64.h \
185 src/data-types/carray.h \
186 src/data-types/charconv.h \
187 src/data-types/chash.h \
188 src/data-types/cinthash.h \
189 src/data-types/clist.h \
190 src/data-types/connect.h \
191 src/data-types/hmac-md5.h \
192 src/data-types/mail.h \
193 src/data-types/mail_cache_db.h \
194 src/data-types/mail_cache_db_types.h \
195 src/data-types/maillock.h \
196 src/data-types/mailsem.h \
197 src/data-types/mailstream.h \
198 src/data-types/mailstream_helper.h \
199 src/data-types/mailstream_low.h \
200 src/data-types/mailstream_socket.h \
201 src/data-types/mailstream_ssl.h \
202 src/data-types/mailstream_types.h \
203 src/data-types/mapping.h \
204 src/data-types/md5.h \
205 src/data-types/md5global.h \
206 src/data-types/mmapstring.h \
207 src/engine/mailengine.h \
208 src/engine/mailprivacy.h \
209 src/engine/mailprivacy_gnupg.h \
210 src/engine/mailprivacy_smime.h \
211 src/engine/mailprivacy_tools.h \
212 src/engine/mailprivacy_types.h \
213 src/main/libetpan.h \
214 src/main/libetpan_version.h \
215 src/driver/interface/maildriver.h \
216 src/driver/interface/maildriver_errors.h \
217 src/driver/interface/maildriver_tools.h \
218 src/driver/interface/maildriver_types.h \
219 src/driver/interface/maildriver_types_helper.h \
220 src/driver/interface/mailfolder.h \
221 src/driver/interface/mailmessage.h \
222 src/driver/interface/mailmessage_tools.h \
223 src/driver/interface/mailmessage_types.h \
224 src/driver/interface/mailstorage.h \
225 src/driver/interface/mailstorage_tools.h \
226 src/driver/interface/mailstorage_types.h \
227 src/driver/tools/generic_cache.h \
228 src/driver/tools/generic_cache_types.h \
229 src/driver/tools/imfcache.h \
230 src/driver/tools/mailthread.h \
231 src/driver/tools/mailthread_types.h \
232 src/low-level/imap/mailimap.h \
233 src/low-level/imap/mailimap_helper.h \
234 src/low-level/imap/mailimap_keywords.h \
235 src/low-level/imap/mailimap_parser.h \
236 src/low-level/imap/mailimap_print.h \
237 src/low-level/imap/mailimap_sender.h \
238 src/low-level/imap/mailimap_socket.h \
239 src/low-level/imap/mailimap_ssl.h \
240 src/low-level/imap/mailimap_types.h \
241 src/low-level/imap/mailimap_types_helper.h \
242 src/low-level/imf/mailimf.h \
243 src/low-level/imf/mailimf_types.h \
244 src/low-level/imf/mailimf_types_helper.h \
245 src/low-level/imf/mailimf_write.h \
246 src/low-level/imf/mailimf_write_file.h \
247 src/low-level/imf/mailimf_write_generic.h \
248 src/low-level/imf/mailimf_write_mem.h \
249 src/low-level/maildir/maildir.h \
250 src/low-level/maildir/maildir_types.h \
251 src/low-level/mbox/mailmbox.h \
252 src/low-level/mbox/mailmbox_parse.h \
253 src/low-level/mbox/mailmbox_types.h \
254 src/low-level/mh/mailmh.h \
255 src/low-level/mime/mailmime.h \
256 src/low-level/mime/mailmime_content.h \
257 src/low-level/mime/mailmime_decode.h \
258 src/low-level/mime/mailmime_disposition.h \
259 src/low-level/mime/mailmime_types.h \
260 src/low-level/mime/mailmime_types_helper.h \
261 src/low-level/mime/mailmime_write.h \
262 src/low-level/mime/mailmime_write_file.h \
263 src/low-level/mime/mailmime_write_generic.h \
264 src/low-level/mime/mailmime_write_mem.h \
265 src/low-level/nntp/newsnntp.h \
266 src/low-level/nntp/newsnntp_socket.h \
267 src/low-level/nntp/newsnntp_ssl.h \
268 src/low-level/nntp/newsnntp_types.h \
269 src/low-level/pop3/mailpop3.h \
270 src/low-level/pop3/mailpop3_helper.h \
271 src/low-level/pop3/mailpop3_socket.h \
272 src/low-level/pop3/mailpop3_ssl.h \
273 src/low-level/pop3/mailpop3_types.h \
274 src/low-level/smtp/mailsmtp.h \
275 src/low-level/smtp/mailsmtp_helper.h \
276 src/low-level/smtp/mailsmtp_socket.h \
277 src/low-level/smtp/mailsmtp_ssl.h \
278 src/low-level/smtp/mailsmtp_types.h \
279 src/driver/implementation/data-message/data_message_driver.h \
280 src/driver/implementation/db/dbdriver.h \
281 src/driver/implementation/db/dbdriver_message.h \
282 src/driver/implementation/db/dbdriver_types.h \
283 src/driver/implementation/db/dbstorage.h \
284 src/driver/implementation/hotmail/hotmailstorage.h \
285 src/driver/implementation/imap/imapdriver.h \
286 src/driver/implementation/imap/imapdriver_cached.h \
287 src/driver/implementation/imap/imapdriver_cached_message.h \
288 src/driver/implementation/imap/imapdriver_message.h \
289 src/driver/implementation/imap/imapdriver_tools.h \
290 src/driver/implementation/imap/imapdriver_types.h \
291 src/driver/implementation/imap/imapstorage.h \
292 src/driver/implementation/maildir/maildirdriver.h \
293 src/driver/implementation/maildir/maildirdriver_cached.h \
294 src/driver/implementation/maildir/maildirdriver_cached_message.h \
295 src/driver/implementation/maildir/maildirdriver_message.h \
296 src/driver/implementation/maildir/maildirdriver_tools.h \
297 src/driver/implementation/maildir/maildirdriver_types.h \
298 src/driver/implementation/maildir/maildirstorage.h \
299 src/driver/implementation/mbox/mboxdriver.h \
300 src/driver/implementation/mbox/mboxdriver_cached.h \
301 src/driver/implementation/mbox/mboxdriver_cached_message.h \
302 src/driver/implementation/mbox/mboxdriver_message.h \
303 src/driver/implementation/mbox/mboxdriver_tools.h \
304 src/driver/implementation/mbox/mboxdriver_types.h \
305 src/driver/implementation/mbox/mboxstorage.h \
306 src/driver/implementation/mh/mhdriver.h \
307 src/driver/implementation/mh/mhdriver_cached.h \
308 src/driver/implementation/mh/mhdriver_cached_message.h \
309 src/driver/implementation/mh/mhdriver_message.h \
310 src/driver/implementation/mh/mhdriver_tools.h \
311 src/driver/implementation/mh/mhdriver_types.h \
312 src/driver/implementation/mh/mhstorage.h \
313 src/driver/implementation/mime-message/mime_message_driver.h \
314 src/driver/implementation/nntp/nntpdriver.h \
315 src/driver/implementation/nntp/nntpdriver_cached.h \
316 src/driver/implementation/nntp/nntpdriver_cached_message.h \
317 src/driver/implementation/nntp/nntpdriver_message.h \
318 src/driver/implementation/nntp/nntpdriver_tools.h \
319 src/driver/implementation/nntp/nntpdriver_types.h \
320 src/driver/implementation/nntp/nntpstorage.h \
321 src/driver/implementation/pop3/pop3driver.h \
322 src/driver/implementation/pop3/pop3driver_cached.h \
323 src/driver/implementation/pop3/pop3driver_cached_message.h \
324 src/driver/implementation/pop3/pop3driver_message.h \
325 src/driver/implementation/pop3/pop3driver_tools.h \
326 src/driver/implementation/pop3/pop3driver_types.h \
327 src/driver/implementation/pop3/pop3storage.h
328SOURCES += src/data-types/base64.c \
329 src/data-types/carray.c \
330 src/data-types/charconv.c \
331 src/data-types/chash.c \
332 src/data-types/cinthash.c \
333 src/data-types/clist.c \
334 src/data-types/connect.c \
335 src/data-types/mail_cache_db.c \
336 src/data-types/maillock.c \
337 src/data-types/mailsem.c \
338 src/data-types/mailstream.c \
339 src/data-types/mailstream_helper.c \
340 src/data-types/mailstream_low.c \
341 src/data-types/mailstream_socket.c \
342 src/data-types/mailstream_ssl.c \
343 src/data-types/mapping.c \
344 src/data-types/md5.c \
345 src/data-types/mmapstring.c \
346 src/engine/mailengine.c \
347 src/engine/mailprivacy.c \
348 src/engine/mailprivacy_gnupg.c \
349 src/engine/mailprivacy_smime.c \
350 src/engine/mailprivacy_tools.c \
351 src/main/libetpan_version.c \
352 src/driver/interface/maildriver.c \
353 src/driver/interface/maildriver_tools.c \
354 src/driver/interface/maildriver_types.c \
355 src/driver/interface/maildriver_types_helper.c \
356 src/driver/interface/mailfolder.c \
357 src/driver/interface/mailmessage.c \
358 src/driver/interface/mailmessage_tools.c \
359 src/driver/interface/mailmessage_types.c \
360 src/driver/interface/mailstorage.c \
361 src/driver/interface/mailstorage_tools.c \
362 src/driver/tools/generic_cache.c \
363 src/driver/tools/imfcache.c \
364 src/driver/tools/mailthread.c \
365 src/driver/tools/mailthread_types.c \
366 src/low-level/imap/mailimap.c \
367 src/low-level/imap/mailimap_helper.c \
368 src/low-level/imap/mailimap_keywords.c \
369 src/low-level/imap/mailimap_parser.c \
370 src/low-level/imap/mailimap_print.c \
371 src/low-level/imap/mailimap_sender.c \
372 src/low-level/imap/mailimap_socket.c \
373 src/low-level/imap/mailimap_ssl.c \
374 src/low-level/imap/mailimap_types.c \
375 src/low-level/imap/mailimap_types_helper.c \
376 src/low-level/imf/mailimf.c \
377 src/low-level/imf/mailimf_types.c \
378 src/low-level/imf/mailimf_types_helper.c \
379 src/low-level/imf/mailimf_write.c \
380 src/low-level/imf/mailimf_write_file.c \
381 src/low-level/imf/mailimf_write_generic.c \
382 src/low-level/imf/mailimf_write_mem.c \
383 src/low-level/maildir/maildir.c \
384 src/low-level/mbox/mailmbox.c \
385 src/low-level/mbox/mailmbox_parse.c \
386 src/low-level/mbox/mailmbox_types.c \
387 src/low-level/mh/mailmh.c \
388 src/low-level/mime/mailmime.c \
389 src/low-level/mime/mailmime_content.c \
390 src/low-level/mime/mailmime_decode.c \
391 src/low-level/mime/mailmime_disposition.c \
392 src/low-level/mime/mailmime_types.c \
393 src/low-level/mime/mailmime_types_helper.c \
394 src/low-level/mime/mailmime_write.c \
395 src/low-level/mime/mailmime_write_file.c \
396 src/low-level/mime/mailmime_write_generic.c \
397 src/low-level/mime/mailmime_write_mem.c \
398 src/low-level/nntp/newsnntp.c \
399 src/low-level/nntp/newsnntp_socket.c \
400 src/low-level/nntp/newsnntp_ssl.c \
401 src/low-level/pop3/mailpop3.c \
402 src/low-level/pop3/mailpop3_helper.c \
403 src/low-level/pop3/mailpop3_socket.c \
404 src/low-level/pop3/mailpop3_ssl.c \
405 src/low-level/smtp/mailsmtp.c \
406 src/low-level/smtp/mailsmtp_helper.c \
407 src/low-level/smtp/mailsmtp_socket.c \
408 src/low-level/smtp/mailsmtp_ssl.c \
409 src/driver/implementation/data-message/data_message_driver.c \
410 src/driver/implementation/db/dbdriver.c \
411 src/driver/implementation/db/dbdriver_message.c \
412 src/driver/implementation/db/dbstorage.c \
413 src/driver/implementation/hotmail/hotmailstorage.c \
414 src/driver/implementation/imap/imapdriver.c \
415 src/driver/implementation/imap/imapdriver_cached.c \
416 src/driver/implementation/imap/imapdriver_cached_message.c \
417 src/driver/implementation/imap/imapdriver_message.c \
418 src/driver/implementation/imap/imapdriver_tools.c \
419 src/driver/implementation/imap/imapstorage.c \
420 src/driver/implementation/maildir/maildirdriver.c \
421 src/driver/implementation/maildir/maildirdriver_cached.c \
422 src/driver/implementation/maildir/maildirdriver_cached_message.c \
423 src/driver/implementation/maildir/maildirdriver_message.c \
424 src/driver/implementation/maildir/maildirdriver_tools.c \
425 src/driver/implementation/maildir/maildirstorage.c \
426 src/driver/implementation/mbox/mboxdriver.c \
427 src/driver/implementation/mbox/mboxdriver_cached.c \
428 src/driver/implementation/mbox/mboxdriver_cached_message.c \
429 src/driver/implementation/mbox/mboxdriver_message.c \
430 src/driver/implementation/mbox/mboxdriver_tools.c \
431 src/driver/implementation/mbox/mboxstorage.c \
432 src/driver/implementation/mh/mhdriver.c \
433 src/driver/implementation/mh/mhdriver_cached.c \
434 src/driver/implementation/mh/mhdriver_cached_message.c \
435 src/driver/implementation/mh/mhdriver_message.c \
436 src/driver/implementation/mh/mhdriver_tools.c \
437 src/driver/implementation/mh/mhstorage.c \
438 src/driver/implementation/mime-message/mime_message_driver.c \
439 src/driver/implementation/nntp/nntpdriver.c \
440 src/driver/implementation/nntp/nntpdriver_cached.c \
441 src/driver/implementation/nntp/nntpdriver_cached_message.c \
442 src/driver/implementation/nntp/nntpdriver_message.c \
443 src/driver/implementation/nntp/nntpdriver_tools.c \
444 src/driver/implementation/nntp/nntpstorage.c \
445 src/driver/implementation/pop3/pop3driver.c \
446 src/driver/implementation/pop3/pop3driver_cached.c \
447 src/driver/implementation/pop3/pop3driver_cached_message.c \
448 src/driver/implementation/pop3/pop3driver_message.c \
449 src/driver/implementation/pop3/pop3driver_tools.c \
450 src/driver/implementation/pop3/pop3storage.c
diff --git a/libetpan/src/data-types/base64.c b/libetpan/src/data-types/base64.c
new file mode 100644
index 0000000..58a2c04
--- a/dev/null
+++ b/libetpan/src/data-types/base64.c
@@ -0,0 +1,143 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - Juergen Graf
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "base64.h"
37
38#include <stdlib.h>
39
40#define OUTPUT_SIZE 513
41#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
42
43static char index_64[128] = {
44 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
45 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
46 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
47 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
48 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
49 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
50 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
51 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
52};
53
54static char basis_64[] =
55 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
56
57char * encode_base64(const char * in, int len)
58{
59 char * output, * tmp;
60 unsigned char oval;
61 int out_len;
62
63 out_len = ((len + 2) / 3 * 4) + 1;
64
65 if ((len > 0) && (in == NULL))
66 return NULL;
67
68 output = malloc(out_len);
69 if (!output)
70 return NULL;
71
72 tmp = output;
73 while (len >= 3) {
74 *tmp++ = basis_64[in[0] >> 2];
75 *tmp++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)];
76 *tmp++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
77 *tmp++ = basis_64[in[2] & 0x3f];
78 in += 3;
79 len -= 3;
80 }
81 if (len > 0) {
82 *tmp++ = basis_64[in[0] >> 2];
83 oval = (in[0] << 4) & 0x30;
84 if (len > 1) oval |= in[1] >> 4;
85 *tmp++ = basis_64[oval];
86 *tmp++ = (len < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c];
87 *tmp++ = '=';
88 }
89
90 *tmp = '\0';
91
92 return output;
93}
94
95char * decode_base64(const char * in, int len)
96{
97 char * output, * out;
98 int i, c1, c2, c3, c4, out_len;
99
100 out_len = 0;
101
102 output = malloc(OUTPUT_SIZE);
103 if (output == NULL)
104 return NULL;
105 out = output;
106
107 if (in[0] == '+' && in[1] == ' ')
108 in += 2;
109
110 for (i = 0; i < (len / 4); i++) {
111 c1 = in[0];
112 c2 = in[1];
113 c3 = in[2];
114 c4 = in[3];
115 if (CHAR64(c1) == -1 || CHAR64(c2) == -1 ||
116 (c3 != '=' && CHAR64(c3) == -1) ||
117 (c4 != '=' && CHAR64(c4) == -1))
118 return NULL;
119
120 in += 4;
121 *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
122 if (++out_len >= OUTPUT_SIZE)
123 return NULL;
124
125 if (c3 != '=') {
126 *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
127 if (++out_len >= OUTPUT_SIZE)
128 return NULL;
129
130 if (c4 != '=') {
131 *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
132 if (++out_len >= OUTPUT_SIZE)
133 return NULL;
134 }
135 }
136 }
137
138 *output = 0;
139
140 return out;
141}
142
143
diff --git a/libetpan/src/data-types/base64.h b/libetpan/src/data-types/base64.h
new file mode 100644
index 0000000..1430207
--- a/dev/null
+++ b/libetpan/src/data-types/base64.h
@@ -0,0 +1,59 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - Juergen Graf
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef BASE64_H
37#define BASE64_H
38
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/**
44 * creates (malloc) a new base64 encoded string from a standard 8bit string
45 * don't forget to free it when time comes ;)
46 */
47char * encode_base64(const char * in, int len);
48
49/**
50 * creates (malloc) a new standard 8bit string from an base64 encoded string
51 * don't forget to free it when time comes ;)
52 */
53char * decode_base64(const char * in, int len);
54
55#ifdef __cplusplus
56}
57#endif
58
59#endif
diff --git a/libetpan/src/data-types/carray.c b/libetpan/src/data-types/carray.c
new file mode 100644
index 0000000..f1e618b
--- a/dev/null
+++ b/libetpan/src/data-types/carray.c
@@ -0,0 +1,142 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * carray - Implements simple dynamic pointer arrays
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#include <stdlib.h>
40#include <string.h>
41#include "carray.h"
42
43carray * carray_new(unsigned int initsize) {
44 carray * array;
45
46 array = (carray *) malloc(sizeof(carray));
47 if (!array) return NULL;
48
49 array->len = 0;
50 array->max = initsize;
51 array->array = (void **) malloc(sizeof(void *) * initsize);
52 if (!array->array) {
53 free(array);
54 return NULL;
55 }
56 return array;
57}
58
59int carray_add(carray * array, void * data, unsigned int * index) {
60 int r;
61
62 r = carray_set_size(array, array->len + 1);
63 if (r < 0)
64 return r;
65
66 array->array[array->len - 1] = data;
67 if (index != NULL)
68 * index = array->len - 1;
69
70 return 0;
71}
72
73int carray_set_size(carray * array, unsigned int new_size)
74{
75 if (new_size > array->max) {
76 unsigned int n = array->max * 2;
77 void * new;
78
79 while (n <= new_size)
80 n *= 2;
81
82 new = (void **) realloc(array->array, sizeof(void *) * n);
83 if (!new)
84 return -1;
85 array->array = new;
86 array->max = n;
87 }
88 array->len = new_size;
89
90 return 0;
91}
92
93int carray_delete_fast(carray * array, unsigned int indx) {
94 if (indx >= array->len)
95 return -1;
96
97 array->array[indx] = NULL;
98
99 return 0;
100}
101
102int carray_delete(carray * array, unsigned int indx) {
103 if (indx >= array->len)
104 return -1;
105
106 if (indx != --array->len)
107 array->array[indx] = array->array[array->len];
108 return 0;
109}
110
111int carray_delete_slow(carray * array, unsigned int indx) {
112 if (indx >= array->len)
113 return -1;
114
115 if (indx != --array->len)
116 memmove(array->array + indx, array->array + indx + 1,
117 (array->len - indx) * sizeof(void *));
118 return 0;
119}
120
121#ifdef NO_MACROS
122void ** carray_data(carray * array) {
123 return array->array;
124}
125
126unsigned int carray_count(carray * array) {
127 return array->len;
128}
129
130void * carray_get(carray * array, unsigned int indx) {
131 return array->array[indx];
132}
133
134void carray_set(carray * array, unsigned int indx, void * value) {
135 array->array[indx] = value;
136}
137#endif
138
139void carray_free(carray * array) {
140 free(array->array);
141 free(array);
142}
diff --git a/libetpan/src/data-types/carray.h b/libetpan/src/data-types/carray.h
new file mode 100644
index 0000000..f906c57
--- a/dev/null
+++ b/libetpan/src/data-types/carray.h
@@ -0,0 +1,123 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * carray - Implements simple dynamic pointer arrays
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CARRAY_H
40#define CARRAY_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46struct carray_s {
47 void ** array;
48 unsigned int len;
49 unsigned int max;
50};
51
52typedef struct carray_s carray;
53
54/* Creates a new array of pointers, with initsize preallocated cells */
55carray * carray_new(unsigned int initsize);
56
57/* Adds the pointer to data in the array.
58 Returns the index of the pointer in the array or -1 on error */
59int carray_add(carray * array, void * data, unsigned int * index);
60
61int carray_set_size(carray * array, unsigned int new_size);
62
63/* Removes the cell at this index position. Returns TRUE on success.
64 Order of elements in the array IS changed. */
65int carray_delete(carray * array, unsigned int indx);
66
67/* Removes the cell at this index position. Returns TRUE on success.
68 Order of elements in the array IS not changed. */
69int carray_delete_slow(carray * array, unsigned int indx);
70
71/* remove without decreasing the size of the array */
72int carray_delete_fast(carray * array, unsigned int indx);
73
74/* Some of the following routines can be implemented as macros to
75 be faster. If you don't want it, define NO_MACROS */
76#ifdef NO_MACROS
77
78/* Returns the array itself */
79void ** carray_data(carray *);
80
81/* Returns the number of elements in the array */
82int carray_count(carray *);
83
84/* Returns the contents of one cell */
85void * carray_get(carray * array, unsigned int indx);
86
87/* Sets the contents of one cell */
88void carray_set(carray * array, unsigned int indx, void * value);
89
90#else
91
92#if 0
93#define carray_data(a) (a->array)
94#define carray_count(a) (a->len)
95#define carray_get(a, indx) (a->array[indx])
96#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0)
97#endif
98
99static inline void ** carray_data(carray * array) {
100 return array->array;
101}
102
103static inline unsigned int carray_count(carray * array) {
104 return array->len;
105}
106
107static inline void * carray_get(carray * array, unsigned int indx) {
108 return array->array[indx];
109}
110
111static inline void carray_set(carray * array,
112 unsigned int indx, void * value) {
113 array->array[indx] = value;
114}
115#endif
116
117void carray_free(carray * array);
118
119#ifdef __cplusplus
120}
121#endif
122
123#endif
diff --git a/libetpan/src/data-types/charconv.c b/libetpan/src/data-types/charconv.c
new file mode 100644
index 0000000..28549c9
--- a/dev/null
+++ b/libetpan/src/data-types/charconv.c
@@ -0,0 +1,251 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "charconv.h"
37
38#include "config.h"
39#ifdef HAVE_ICONV
40#include <iconv.h>
41#endif
42#include <stdlib.h>
43#include <string.h>
44#include <stdio.h>
45#include <errno.h>
46
47#include "mmapstring.h"
48
49#ifdef HAVE_ICONV
50static size_t mail_iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft,
51 char **outbuf, size_t *outbytesleft,
52 char **inrepls, char *outrepl)
53{
54 size_t ret = 0, ret1;
55 /* XXX - force const to mutable */
56 char *ib = (char *) *inbuf;
57 size_t ibl = *inbytesleft;
58 char *ob = *outbuf;
59 size_t obl = *outbytesleft;
60
61 for (;;)
62 {
63#ifdef HAVE_ICONV_PROTO_CONST
64 ret1 = iconv (cd, (const char **) &ib, &ibl, &ob, &obl);
65#else
66 ret1 = iconv (cd, &ib, &ibl, &ob, &obl);
67#endif
68 if (ret1 != (size_t)-1)
69 ret += ret1;
70 if (ibl && obl && errno == EILSEQ)
71 {
72 if (inrepls)
73 {
74 /* Try replacing the input */
75 char **t;
76 for (t = inrepls; *t; t++)
77 {
78 char *ib1 = *t;
79 size_t ibl1 = strlen (*t);
80 char *ob1 = ob;
81 size_t obl1 = obl;
82#ifdef HAVE_ICONV_PROTO_CONST
83 iconv (cd, (const char **) &ib1, &ibl1, &ob1, &obl1);
84#else
85 iconv (cd, &ib1, &ibl1, &ob1, &obl1);
86#endif
87 if (!ibl1)
88 {
89 ++ib, --ibl;
90 ob = ob1, obl = obl1;
91 ++ret;
92 break;
93 }
94 }
95 if (*t)
96 continue;
97 }
98 if (outrepl)
99 {
100 /* Try replacing the output */
101 size_t n = strlen (outrepl);
102 if (n <= obl)
103 {
104 memcpy (ob, outrepl, n);
105 ++ib, --ibl;
106 ob += n, obl -= n;
107 ++ret;
108 continue;
109 }
110 }
111 }
112 *inbuf = ib, *inbytesleft = ibl;
113 *outbuf = ob, *outbytesleft = obl;
114 return ret;
115 }
116}
117#endif
118
119int charconv(const char * tocode, const char * fromcode,
120 const char * str, size_t length,
121 char ** result)
122{
123#ifndef HAVE_ICONV
124 return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET;
125#else
126 iconv_t conv;
127 size_t r;
128 char * out;
129 char * pout;
130 size_t out_size;
131 size_t old_out_size;
132 size_t count;
133 int res;
134
135 conv = iconv_open(tocode, fromcode);
136 if (conv == (iconv_t) -1) {
137 res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET;
138 goto err;
139 }
140
141 out_size = 4 * length;
142
143 out = malloc(out_size + 1);
144 if (out == NULL) {
145 res = MAIL_CHARCONV_ERROR_MEMORY;
146 goto close_iconv;
147 }
148
149 pout = out;
150 old_out_size = out_size;
151
152 r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?");
153
154 if (r == (size_t) -1) {
155 res = MAIL_CHARCONV_ERROR_CONV;
156 goto free;
157 }
158
159 iconv_close(conv);
160
161 * pout = '\0';
162 count = old_out_size - out_size;
163 pout = realloc(out, count + 1);
164 if (pout != NULL)
165 out = pout;
166
167 * result = out;
168
169 return MAIL_CHARCONV_NO_ERROR;
170
171 free:
172 free(out);
173 close_iconv:
174 iconv_close(conv);
175 err:
176 return res;
177#endif
178};
179
180int charconv_buffer(const char * tocode, const char * fromcode,
181 const char * str, size_t length,
182 char ** result, size_t * result_len)
183{
184#ifndef HAVE_ICONV
185 return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET;
186#else
187 iconv_t conv;
188 size_t iconv_r;
189 int r;
190 char * out;
191 char * pout;
192 size_t out_size;
193 size_t old_out_size;
194 size_t count;
195 MMAPString * mmapstr;
196 int res;
197
198 conv = iconv_open(tocode, fromcode);
199 if (conv == (iconv_t) -1) {
200 res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET;
201 goto err;
202 }
203
204 out_size = 4 * length;
205
206 mmapstr = mmap_string_sized_new(out_size + 1);
207 if (mmapstr == NULL) {
208 res = MAIL_CHARCONV_ERROR_MEMORY;
209 goto err;
210 }
211
212 out = mmapstr->str;
213
214 pout = out;
215 old_out_size = out_size;
216
217 iconv_r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?");
218
219 if (iconv_r == (size_t) -1) {
220 res = MAIL_CHARCONV_ERROR_CONV;
221 goto free;
222 }
223
224 iconv_close(conv);
225
226 * pout = '\0';
227
228 count = old_out_size - out_size;
229
230 r = mmap_string_ref(mmapstr);
231 if (r < 0) {
232 res = MAIL_CHARCONV_ERROR_MEMORY;
233 goto free;
234 }
235
236 * result = out;
237 * result_len = count;
238
239 return MAIL_CHARCONV_NO_ERROR;
240
241 free:
242 mmap_string_free(mmapstr);
243 err:
244 return -1;
245#endif
246};
247
248void charconv_buffer_free(char * str)
249{
250 mmap_string_unref(str);
251}
diff --git a/libetpan/src/data-types/charconv.h b/libetpan/src/data-types/charconv.h
new file mode 100644
index 0000000..8a68f7b
--- a/dev/null
+++ b/libetpan/src/data-types/charconv.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef CHARCONV_H
37
38#define CHARCONV_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45
46enum {
47 MAIL_CHARCONV_NO_ERROR = 0,
48 MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET,
49 MAIL_CHARCONV_ERROR_MEMORY,
50 MAIL_CHARCONV_ERROR_CONV,
51};
52
53int charconv(const char * tocode, const char * fromcode,
54 const char * str, size_t length,
55 char ** result);
56
57int charconv_buffer(const char * tocode, const char * fromcode,
58 const char * str, size_t length,
59 char ** result, size_t * result_len);
60
61void charconv_buffer_free(char * str);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/src/data-types/chash.c b/libetpan/src/data-types/chash.c
new file mode 100644
index 0000000..a89eb91
--- a/dev/null
+++ b/libetpan/src/data-types/chash.c
@@ -0,0 +1,394 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * chash - Implements generic hash tables.
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#include <stdlib.h>
40#include <string.h>
41
42#include "chash.h"
43
44/* This defines the maximum (average) number of entries per bucket.
45 The hash is resized everytime inserting an entry makes the
46 average go over that value. */
47#define CHASH_MAXDEPTH 3
48
49static inline unsigned int chash_func(const char * key, unsigned int len) {
50#if 0
51 register unsigned int c = 0, t;
52 register const char * k = key;
53
54 while (len--) {
55 c += (c << 4) + *k++;
56 if ((t = c & 0xF0000000)) {
57 c ^= t >> 24;
58 c ^= t;
59 }
60 }
61 return c;
62#endif
63 register unsigned int c = 5381;
64 register const char * k = key;
65
66 while (len--) {
67 c = ((c << 5) + c) + *k++;
68 }
69
70 return c;
71}
72
73static inline char * chash_dup(const void * data, unsigned int len)
74{
75 void * r;
76
77 r = (char *) malloc(len);
78 if (!r)
79 return NULL;
80 memcpy(r, data, len);
81 return r;
82}
83
84chash * chash_new(unsigned int size, int flags)
85{
86 chash * h;
87
88 h = (chash *) malloc(sizeof(chash));
89 if (h == NULL)
90 return NULL;
91
92 h->count = 0;
93 h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
94 if (h->cells == NULL) {
95 free(h);
96 return NULL;
97 }
98 h->size = size;
99 h->copykey = flags & CHASH_COPYKEY;
100 h->copyvalue = flags & CHASH_COPYVALUE;
101
102 return h;
103}
104
105int chash_get(chash * hash,
106 chashdatum * key, chashdatum * result)
107{
108 unsigned int func;
109 chashiter * iter;
110
111 func = chash_func(key->data, key->len);
112
113 /* look for the key in existing cells */
114 iter = hash->cells[func % hash->size];
115 while (iter) {
116 if (iter->key.len == key->len && iter->func == func
117 && !memcmp(iter->key.data, key->data, key->len)) {
118 * result = iter->value; /* found */
119
120 return 0;
121 }
122 iter = iter->next;
123 }
124
125 return -1;
126}
127
128int chash_set(chash * hash,
129 chashdatum * key,
130 chashdatum * value,
131 chashdatum * oldvalue)
132{
133 unsigned int func, indx;
134 chashiter * iter, * cell;
135 int r;
136
137 if (hash->count > hash->size * CHASH_MAXDEPTH) {
138 r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1);
139 if (r < 0)
140 goto err;
141 }
142
143 func = chash_func(key->data, key->len);
144 indx = func % hash->size;
145
146 /* look for the key in existing cells */
147 iter = hash->cells[indx];
148 while (iter) {
149 if (iter->key.len == key->len && iter->func == func
150 && !memcmp(iter->key.data, key->data, key->len)) {
151 /* found, replacing entry */
152 if (hash->copyvalue) {
153 char * data;
154
155 data = chash_dup(value->data, value->len);
156 if (data == NULL)
157 goto err;
158
159 free(iter->value.data);
160 iter->value.data = data;
161 iter->value.len = value->len;
162 } else {
163 if (oldvalue != NULL) {
164 oldvalue->data = iter->value.data;
165 oldvalue->len = iter->value.len;
166 }
167 iter->value.data = value->data;
168 iter->value.len = value->len;
169 }
170 if (!hash->copykey)
171 iter->key.data = key->data;
172
173 if (oldvalue != NULL) {
174 oldvalue->data = value->data;
175 oldvalue->len = value->len;
176 }
177
178 return 0;
179 }
180 iter = iter->next;
181 }
182
183 if (oldvalue != NULL) {
184 oldvalue->data = NULL;
185 oldvalue->len = 0;
186 }
187
188 /* not found, adding entry */
189 cell = (struct chashcell *) malloc(sizeof(struct chashcell));
190 if (cell == NULL)
191 goto err;
192
193 if (hash->copykey) {
194 cell->key.data = chash_dup(key->data, key->len);
195 if (cell->key.data == NULL)
196 goto free;
197 }
198 else
199 cell->key.data = key->data;
200
201 cell->key.len = key->len;
202 if (hash->copyvalue) {
203 cell->value.data = chash_dup(value->data, value->len);
204 if (cell->value.data == NULL)
205 goto free_key_data;
206 }
207 else
208 cell->value.data = value->data;
209
210 cell->value.len = value->len;
211 cell->func = func;
212 cell->next = hash->cells[indx];
213 hash->cells[indx] = cell;
214 hash->count++;
215
216 return 0;
217
218 free_key_data:
219 if (hash->copykey)
220 free(cell->key.data);
221 free:
222 free(cell);
223 err:
224 return -1;
225}
226
227int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue)
228{
229 /* chashdatum result = { NULL, TRUE }; */
230 unsigned int func, indx;
231 chashiter * iter, * old;
232
233 /*
234 if (!keylen)
235 keylen = strlen(key) + 1;
236 */
237
238 func = chash_func(key->data, key->len);
239 indx = func % hash->size;
240
241 /* look for the key in existing cells */
242 old = NULL;
243 iter = hash->cells[indx];
244 while (iter) {
245 if (iter->key.len == key->len && iter->func == func
246 && !memcmp(iter->key.data, key->data, key->len)) {
247 /* found, deleting */
248 if (old)
249 old->next = iter->next;
250 else
251 hash->cells[indx] = iter->next;
252 if (hash->copykey)
253 free(iter->key.data);
254 if (hash->copyvalue)
255 free(iter->value.data);
256 else {
257 if (oldvalue != NULL) {
258 oldvalue->data = iter->value.data;
259 oldvalue->len = iter->value.len;
260 }
261 }
262 free(iter);
263 hash->count--;
264 return 0;
265 }
266 old = iter;
267 iter = iter->next;
268 }
269
270 return -1; /* not found */
271}
272
273void chash_free(chash * hash) {
274 unsigned int indx;
275 chashiter * iter, * next;
276
277 /* browse the hash table */
278 for(indx = 0; indx < hash->size; indx++) {
279 iter = hash->cells[indx];
280 while (iter) {
281 next = iter->next;
282 if (hash->copykey)
283 free(iter->key.data);
284 if (hash->copyvalue)
285 free(iter->value.data);
286 free(iter);
287 iter = next;
288 }
289 }
290 free(hash->cells);
291 free(hash);
292}
293
294void chash_clear(chash * hash) {
295 unsigned int indx;
296 chashiter * iter, * next;
297
298 /* browse the hash table */
299 for(indx = 0; indx < hash->size; indx++) {
300 iter = hash->cells[indx];
301 while (iter) {
302 next = iter->next;
303 if (hash->copykey)
304 free(iter->key.data);
305 if (hash->copyvalue)
306 free(iter->value.data);
307 free(iter);
308 iter = next;
309 }
310 }
311 memset(hash->cells, 0, hash->size * sizeof(* hash->cells));
312 hash->count = 0;
313}
314
315chashiter * chash_begin(chash * hash) {
316 chashiter * iter;
317 unsigned int indx = 0;
318
319 iter = hash->cells[0];
320 while(!iter) {
321 indx++;
322 if (indx >= hash->size)
323 return NULL;
324 iter = hash->cells[indx];
325 }
326 return iter;
327}
328
329chashiter * chash_next(chash * hash, chashiter * iter) {
330 unsigned int indx;
331
332 if (!iter)
333 return NULL;
334
335 indx = iter->func % hash->size;
336 iter = iter->next;
337
338 while(!iter) {
339 indx++;
340 if (indx >= hash->size)
341 return NULL;
342 iter = hash->cells[indx];
343 }
344 return iter;
345}
346
347int chash_resize(chash * hash, unsigned int size)
348{
349 struct chashcell ** cells;
350 unsigned int indx, nindx;
351 chashiter * iter, * next;
352
353 if (hash->size == size)
354 return 0;
355
356 cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
357 if (!cells)
358 return -1;
359
360 /* browse initial hash and copy items in second hash */
361 for(indx = 0; indx < hash->size; indx++) {
362 iter = hash->cells[indx];
363 while (iter) {
364 next = iter->next;
365 nindx = iter->func % size;
366 iter->next = cells[nindx];
367 cells[nindx] = iter;
368 iter = next;
369 }
370 }
371 free(hash->cells);
372 hash->size = size;
373 hash->cells = cells;
374
375 return 0;
376}
377
378#ifdef NO_MACROS
379int chash_count(chash * hash) {
380 return hash->count;
381}
382
383int chash_size(chash * hash) {
384 return hash->size;
385}
386
387void chash_value(chashiter * iter, chashdatum * result) {
388 * result = iter->value;
389}
390
391void chash_key(chashiter * iter, chashdatum * result) {
392 * result = iter->key;
393}
394#endif
diff --git a/libetpan/src/data-types/chash.h b/libetpan/src/data-types/chash.h
new file mode 100644
index 0000000..a9a61e5
--- a/dev/null
+++ b/libetpan/src/data-types/chash.h
@@ -0,0 +1,165 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * chash - Implements generic hash tables.
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CHASH_H
40#define CHASH_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46typedef struct {
47 void * data;
48 unsigned int len;
49} chashdatum;
50
51struct chash {
52 unsigned int size;
53 unsigned int count;
54 int copyvalue;
55 int copykey;
56 struct chashcell ** cells;
57};
58
59typedef struct chash chash;
60
61struct chashcell {
62 unsigned int func;
63 chashdatum key;
64 chashdatum value;
65 struct chashcell * next;
66};
67
68typedef struct chashcell chashiter;
69
70#define CHASH_COPYNONE 0
71#define CHASH_COPYKEY 1
72#define CHASH_COPYVALUE 2
73#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE)
74
75#define CHASH_DEFAULTSIZE 13
76
77/* Allocates a new (empty) hash using this initial size and the given flags,
78 specifying which data should be copied in the hash.
79 CHASH_COPYNONE : Keys/Values are not copied.
80 CHASH_COPYKEY : Keys are dupped and freed as needed in the hash.
81 CHASH_COPYVALUE : Values are dupped and freed as needed in the hash.
82 CHASH_COPYALL : Both keys and values are dupped in the hash.
83 */
84chash * chash_new(unsigned int size, int flags);
85
86/* Frees a hash */
87void chash_free(chash * hash);
88
89/* Removes all elements from a hash */
90void chash_clear(chash * hash);
91
92/* Adds an entry in the hash table.
93 Length can be 0 if key/value are strings.
94 If an entry already exists for this key, it is replaced, and its value
95 is returned. Otherwise, the data pointer will be NULL and the length
96 field be set to TRUE or FALSe to indicate success or failure. */
97int chash_set(chash * hash,
98 chashdatum * key,
99 chashdatum * value,
100 chashdatum * oldvalue);
101
102/* Retrieves the data associated to the key if it is found in the hash table.
103 The data pointer and the length will be NULL if not found*/
104int chash_get(chash * hash,
105 chashdatum * key, chashdatum * result);
106
107/* Removes the entry associated to this key if it is found in the hash table,
108 and returns its contents if not dupped (otherwise, pointer will be NULL
109 and len TRUE). If entry is not found both pointer and len will be NULL. */
110int chash_delete(chash * hash,
111 chashdatum * key,
112 chashdatum * oldvalue);
113
114/* Resizes the hash table to the passed size. */
115int chash_resize(chash * hash, unsigned int size);
116
117/* Returns an iterator to the first non-empty entry of the hash table */
118chashiter * chash_begin(chash * hash);
119
120/* Returns the next non-empty entry of the hash table */
121chashiter * chash_next(chash * hash, chashiter * iter);
122
123/* Some of the following routines can be implemented as macros to
124 be faster. If you don't want it, define NO_MACROS */
125#ifdef NO_MACROS
126/* Returns the size of the hash table */
127unsigned int chash_size(chash * hash);
128
129/* Returns the number of entries in the hash table */
130unsigned int chash_count(chash * hash);
131
132/* Returns the key part of the entry pointed by the iterator */
133void chash_key(chashiter * iter, chashdatum * result);
134
135/* Returns the value part of the entry pointed by the iterator */
136void chash_value(chashiter * iter, chashdatum * result);
137
138#else
139static inline unsigned int chash_size(chash * hash)
140{
141 return hash->size;
142}
143
144static inline unsigned int chash_count(chash * hash)
145{
146 return hash->count;
147}
148
149static inline void chash_key(chashiter * iter, chashdatum * result)
150{
151 * result = iter->key;
152}
153
154static inline void chash_value(chashiter * iter, chashdatum * result)
155{
156 * result = iter->value;
157}
158
159#endif
160
161#ifdef __cplusplus
162}
163#endif
164
165#endif
diff --git a/libetpan/src/data-types/cinthash.c b/libetpan/src/data-types/cinthash.c
new file mode 100644
index 0000000..b59eb86
--- a/dev/null
+++ b/libetpan/src/data-types/cinthash.c
@@ -0,0 +1,248 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <stdlib.h>
37#include "cinthash.h"
38
39struct cinthash_list {
40 unsigned long hash;
41 void * data;
42 struct cinthash_list * next;
43};
44
45static struct cinthash_list HASH_LISTHEAD_NEW = { 0, NULL, NULL };
46
47static inline int hash_list_add(cinthash_t * table,
48 unsigned long hash, void * data)
49{
50 struct cinthash_list * ht;
51 int index;
52
53 index = hash % table->hashtable_size;
54
55 ht = malloc(sizeof(struct cinthash_list));
56 if (ht == NULL)
57 return -1;
58
59 ht->hash = hash;
60 ht->data = data;
61 ht->next = table->table[index].next;
62
63 table->table[index].next = ht;
64
65 return 0;
66}
67
68static inline void hash_list_free(struct cinthash_list * list)
69{
70 struct cinthash_list * cur;
71 struct cinthash_list * next;
72
73 next = list;
74 while (next != NULL) {
75 cur = next;
76 next = cur->next;
77 free(cur);
78 }
79}
80
81static inline int hash_list_remove(cinthash_t * table, unsigned long hash)
82{
83 struct cinthash_list * cur;
84 int index;
85
86 index = hash % table->hashtable_size;
87
88 for(cur = &table->table[index] ; cur->next != NULL ; cur = cur->next) {
89 if (cur->next->hash == hash) {
90 struct cinthash_list * hash_data;
91
92 hash_data = cur->next;
93 cur->next = cur->next->next;
94
95 free(hash_data);
96
97 return 0;
98 }
99 }
100
101 return -1;
102}
103
104static inline void * hash_list_find(cinthash_t * table, unsigned long hash)
105{
106 struct cinthash_list * cur;
107 int index;
108
109 index = hash % table->hashtable_size;
110
111 for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) {
112 if (cur->hash == hash)
113 return cur->data;
114 }
115
116 return NULL;
117}
118
119cinthash_t * cinthash_new(unsigned long hashtable_size)
120{
121 cinthash_t * ht;
122 unsigned long i;
123
124 ht = malloc(sizeof(cinthash_t));
125 if (ht == NULL)
126 return NULL;
127
128 ht->table = malloc(sizeof(struct cinthash_list) * hashtable_size);
129 if (ht->table == NULL)
130 return NULL;
131
132 ht->hashtable_size = hashtable_size;
133 ht->count = 0;
134
135 for(i = 0 ; i < hashtable_size ; i++)
136 ht->table[i] = HASH_LISTHEAD_NEW;
137
138 return ht;
139}
140
141void cinthash_free(cinthash_t * table)
142{
143 unsigned long i;
144
145 for(i = 0 ; i < table->hashtable_size ; i++)
146 hash_list_free(table->table[i].next);
147
148 free(table->table);
149
150 free(table);
151}
152
153int cinthash_add(cinthash_t * table, unsigned long hash, void * data)
154{
155 int index;
156
157 index = hash % table->hashtable_size;
158
159 if (table->table[index].data == NULL) {
160 table->table[index].hash = hash;
161 table->table[index].data = data;
162 table->table[index].next = NULL;
163
164 table->count ++;
165
166 return 0;
167 }
168 else {
169 int r;
170
171 r = hash_list_add(table, hash, data);
172 if (r == -1)
173 return -1;
174
175 table->count ++;
176
177 return 0;
178 }
179}
180
181int cinthash_remove(cinthash_t * table, unsigned long hash)
182{
183 int index;
184
185 index = hash % table->hashtable_size;
186
187 if (table->table[index].hash == hash) {
188 table->table[index].hash = 0;
189 table->table[index].data = NULL;
190
191 table->count --;
192
193 return 0;
194 }
195 else {
196 int r;
197
198 r = hash_list_remove(table, hash);
199
200 table->count --;
201
202 return 0;
203 }
204}
205
206void * cinthash_find(cinthash_t * table, unsigned long hash)
207{
208 int index;
209
210 index = hash % table->hashtable_size;
211
212 if (table->table[index].hash == hash)
213 return table->table[index].data;
214
215 return hash_list_find(table, hash);
216}
217
218void cinthash_foreach_key(cinthash_t * table,
219 void (* func)(unsigned long, void *),
220 void * data)
221{
222 unsigned long index;
223 struct cinthash_list * cur;
224
225 for(index = 0 ; index < table->hashtable_size ; index ++) {
226 if (table->table[index].data != NULL) {
227 func(table->table[index].hash, data);
228 for(cur = table->table[index].next ; cur != NULL ; cur = cur->next)
229 func(cur->hash, data);
230 }
231 }
232}
233
234void cinthash_foreach_data(cinthash_t * table,
235 void (* func)(void *, void *),
236 void * data)
237{
238 unsigned long index;
239 struct cinthash_list * cur;
240
241 for(index = 0 ; index < table->hashtable_size ; index ++) {
242 if (table->table[index].data != NULL) {
243 func(table->table[index].data, data);
244 for(cur = table->table[index].next ; cur != NULL ; cur = cur->next)
245 func(cur->data, data);
246 }
247 }
248}
diff --git a/libetpan/src/data-types/cinthash.h b/libetpan/src/data-types/cinthash.h
new file mode 100644
index 0000000..7103d4f
--- a/dev/null
+++ b/libetpan/src/data-types/cinthash.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef CINTHASH_H
37
38#define CINTHASH_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44typedef struct cinthash_t {
45 struct cinthash_list * table;
46 unsigned long hashtable_size ;
47 unsigned long count;
48} cinthash_t;
49
50cinthash_t * cinthash_new(unsigned long hashtable_size);
51void cinthash_free(cinthash_t * table);
52
53int cinthash_add(cinthash_t * table, unsigned long hash, void * data);
54int cinthash_remove(cinthash_t * table, unsigned long hash);
55void * cinthash_find(cinthash_t * table, unsigned long hash);
56
57void cinthash_foreach_key(cinthash_t * table,
58 void (* func)(unsigned long, void *),
59 void * data);
60
61void cinthash_foreach_data(cinthash_t * table,
62 void (* fun)(void *, void *),
63 void * data);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/src/data-types/clist.c b/libetpan/src/data-types/clist.c
new file mode 100644
index 0000000..0b216de
--- a/dev/null
+++ b/libetpan/src/data-types/clist.c
@@ -0,0 +1,265 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * clist - Implements simple generic double-linked pointer lists
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#include <stdlib.h>
40#include "clist.h"
41
42clist * clist_new() {
43 clist * lst;
44
45 lst = (clist *) malloc(sizeof(clist));
46 if (!lst) return NULL;
47
48 lst->first = lst->last = NULL;
49 lst->count = 0;
50
51 return lst;
52}
53
54void clist_free(clist * lst) {
55 clistcell * l1, * l2;
56
57 l1 = lst->first;
58 while (l1) {
59 l2 = l1->next;
60 free(l1);
61 l1 = l2;
62 }
63
64 free(lst);
65}
66
67#ifdef NO_MACROS
68int clist_isempty(clist * lst) {
69 return ((lst->first==lst->last) && (lst->last==NULL));
70}
71
72clistiter * clist_begin(clist * lst) {
73 return lst->first;
74}
75
76clistiter * clist_end(clist * lst) {
77 return lst->last;
78}
79
80clistiter * clist_next(clistiter * iter) {
81 if (iter)
82 return iter->next;
83 else
84 return NULL;
85}
86
87clistiter * clist_previous(clistiter * iter) {
88 if (iter)
89 return iter->previous;
90 else
91 return NULL;
92}
93
94void * clist_content(clistiter * iter) {
95 if (iter)
96 return iter->data;
97 else
98 return NULL;
99}
100
101int clist_count(clist * lst) {
102 return lst->count;
103}
104
105int clist_prepend(clist * lst, void * data) {
106 return clist_insert_before(lst, lst->first, data);
107}
108
109int clist_append(clist * lst, void * data) {
110 return clist_insert_after(lst, lst->last, data);
111}
112#endif
113
114int clist_insert_before(clist * lst, clistiter * iter, void * data) {
115 clistcell * c;
116
117 c = (clistcell *) malloc(sizeof(clistcell));
118 if (!c) return -1;
119
120 c->data = data;
121 lst->count++;
122
123 if (clist_isempty(lst)) {
124 c->previous = c->next = NULL;
125 lst->first = lst->last = c;
126 return 0;
127 }
128
129 if (!iter) {
130 c->previous = lst->last;
131 c->previous->next = c;
132 c->next = NULL;
133 lst->last = c;
134 return 0;
135 }
136
137 c->previous = iter->previous;
138 c->next = iter;
139 c->next->previous = c;
140 if (c->previous)
141 c->previous->next = c;
142 else
143 lst->first = c;
144
145 return 0;
146}
147
148int clist_insert_after(clist * lst, clistiter * iter, void * data) {
149 clistcell * c;
150
151 c = (clistcell *) malloc(sizeof(clistcell));
152 if (!c) return -1;
153
154 c->data = data;
155 lst->count++;
156
157 if (clist_isempty(lst)) {
158 c->previous = c->next = NULL;
159 lst->first = lst->last = c;
160 return 0;
161 }
162
163 if (!iter) {
164 c->previous = lst->last;
165 c->previous->next = c;
166 c->next = NULL;
167 lst->last = c;
168 return 0;
169 }
170
171 c->previous = iter;
172 c->next = iter->next;
173 if (c->next)
174 c->next->previous = c;
175 else
176 lst->last = c;
177 c->previous->next = c;
178
179 return 0;
180}
181
182clistiter * clist_delete(clist * lst, clistiter * iter) {
183 clistiter * ret;
184
185 if (!iter) return NULL;
186
187 if (iter->previous)
188 iter->previous->next = iter->next;
189 else
190 lst->first = iter->next;
191
192 if (iter->next) {
193 iter->next->previous = iter->previous;
194 ret = iter->next;
195 } else {
196 lst->last = iter->previous;
197 ret = NULL;
198 }
199
200 free(iter);
201 lst->count--;
202
203 return ret;
204}
205
206
207
208void clist_foreach(clist * lst, clist_func func, void * data)
209{
210 clistiter * cur;
211
212 for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next)
213 func(cur->data, data);
214}
215
216void clist_concat(clist * dest, clist * src)
217{
218 if (src->first == NULL) {
219 /* do nothing */
220 }
221 else if (dest->last == NULL) {
222 dest->first = src->first;
223 dest->last = src->last;
224 }
225 else {
226 dest->last->next = src->first;
227 src->first->previous = dest->last;
228 dest->last = src->last;
229 }
230
231 dest->count += src->count;
232 src->last = src->first = NULL;
233}
234
235static inline clistiter * internal_clist_nth(clist * lst, int index)
236{
237 clistiter * cur;
238
239 cur = clist_begin(lst);
240 while ((index > 0) && (cur != NULL)) {
241 cur = cur->next;
242 index --;
243 }
244
245 if (cur == NULL)
246 return NULL;
247
248 return cur;
249}
250
251void * clist_nth_data(clist * lst, int index)
252{
253 clistiter * cur;
254
255 cur = internal_clist_nth(lst, index);
256 if (cur == NULL)
257 return NULL;
258
259 return cur->data;
260}
261
262clistiter * clist_nth(clist * lst, int index)
263{
264 return internal_clist_nth(lst, index);
265}
diff --git a/libetpan/src/data-types/clist.h b/libetpan/src/data-types/clist.h
new file mode 100644
index 0000000..0daf1ed
--- a/dev/null
+++ b/libetpan/src/data-types/clist.h
@@ -0,0 +1,133 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * clist - Implements simple generic double-linked pointer lists
5 *
6 * Copyright (c) 1999-2005, Gaël Roualland <gael.roualland@iname.com>
7 * interface changes - 2005 - DINH Viet Hoa
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the libEtPan! project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef CLIST_H
40#define CLIST_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46typedef struct clistcell_s {
47 void * data;
48 struct clistcell_s * previous;
49 struct clistcell_s * next;
50} clistcell;
51
52struct clist_s {
53 clistcell * first;
54 clistcell * last;
55 int count;
56};
57
58typedef struct clist_s clist;
59typedef clistcell clistiter;
60
61/* Allocate a new pointer list */
62clist * clist_new();
63
64/* Destroys a list. Data pointed by data pointers is NOT freed. */
65void clist_free(clist *);
66
67/* Some of the following routines can be implemented as macros to
68 be faster. If you don't want it, define NO_MACROS */
69#ifdef NO_MACROS
70
71/* Returns TRUE if list is empty */
72int clist_isempty(clist *);
73
74/* Returns the number of elements in the list */
75int clist_count(clist *);
76
77/* Returns an iterator to the first element of the list */
78clistiter * clist_begin(clist *);
79
80/* Returns an iterator to the last element of the list */
81clistiter * clist_end(clist *);
82
83/* Returns an iterator to the next element of the list */
84clistiter * clist_next(clistiter *);
85
86/* Returns an iterator to the previous element of the list */
87clistiter * clist_previous(clistiter *);
88
89/* Returns the data pointer of this element of the list */
90void* clist_content(clistiter *);
91
92/* Inserts this data pointer at the beginning of the list */
93int clist_prepend(clist *, void *);
94
95/* Inserts this data pointer at the end of the list */
96int clist_append(clist *, void *);
97#else
98#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL))
99#define clist_count(lst) (lst->count)
100#define clist_begin(lst) (lst->first)
101#define clist_end(lst) (lst->last)
102#define clist_next(iter) (iter ? iter->next : NULL)
103#define clist_previous(iter) (iter ? iter->previous : NULL)
104#define clist_content(iter) (iter ? iter->data : NULL)
105#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data))
106#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data))
107#endif
108
109/* Inserts this data pointer before the element pointed by the iterator */
110int clist_insert_before(clist *, clistiter *, void *);
111
112/* Inserts this data pointer after the element pointed by the iterator */
113int clist_insert_after(clist *, clistiter *, void *);
114
115/* Deletes the element pointed by the iterator.
116 Returns an iterator to the next element. */
117clistiter * clist_delete(clist *, clistiter *);
118
119typedef void (* clist_func)(void *, void *);
120
121void clist_foreach(clist * lst, clist_func func, void * data);
122
123void clist_concat(clist * dest, clist * src);
124
125void * clist_nth_data(clist * lst, int index);
126
127clistiter * clist_nth(clist * lst, int index);
128
129#ifdef __cplusplus
130}
131#endif
132
133#endif
diff --git a/libetpan/src/data-types/connect.c b/libetpan/src/data-types/connect.c
new file mode 100644
index 0000000..bd8da0e
--- a/dev/null
+++ b/libetpan/src/data-types/connect.c
@@ -0,0 +1,86 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "connect.h"
37
38#include <sys/types.h>
39#include <string.h>
40#include <netdb.h>
41#include <netinet/in.h>
42#include <sys/socket.h>
43#include <unistd.h>
44
45uint16_t mail_get_service_port(const char * name, char * protocol)
46{
47 struct servent * service;
48
49 service = getservbyname(name, protocol);
50
51 if (service == NULL)
52 return 0;
53
54 return service->s_port;
55}
56
57int mail_tcp_connect(const char * server, uint16_t port)
58{
59 struct hostent * remotehost;
60 struct sockaddr_in sa;
61 int s;
62 int r;
63
64 s = socket(PF_INET, SOCK_STREAM, 0);
65 if (s == -1)
66 goto err;
67
68 remotehost = gethostbyname(server);
69 if (remotehost == NULL)
70 goto close_socket;
71
72 sa.sin_family = AF_INET;
73 sa.sin_port = htons(port);
74 memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length);
75
76 r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
77 if (r == -1)
78 goto close_socket;
79
80 return s;
81
82 close_socket:
83 close(s);
84 err:
85 return -1;
86}
diff --git a/libetpan/src/data-types/connect.h b/libetpan/src/data-types/connect.h
new file mode 100644
index 0000000..d8cf1ab
--- a/dev/null
+++ b/libetpan/src/data-types/connect.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef CONNECT_H
37
38#define CONNECT_H
39
40#include <inttypes.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46uint16_t mail_get_service_port(const char * name, char * protocol);
47int mail_tcp_connect(const char * server, uint16_t port);
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
54
diff --git a/libetpan/src/data-types/hmac-md5.h b/libetpan/src/data-types/hmac-md5.h
new file mode 100644
index 0000000..87a7d9f
--- a/dev/null
+++ b/libetpan/src/data-types/hmac-md5.h
@@ -0,0 +1,94 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/* hmac-md5.h -- HMAC_MD5 functions
33 */
34
35/*
36 * $Id$
37 */
38
39#ifndef HMAC_MD5_H
40#define HMAC_MD5_H 1
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#define HMAC_MD5_SIZE 16
47
48/* intermediate MD5 context */
49typedef struct HMAC_MD5_CTX_s {
50 MD5_CTX ictx, octx;
51} HMAC_MD5_CTX;
52
53/* intermediate HMAC state
54 * values stored in network byte order (Big Endian)
55 */
56typedef struct HMAC_MD5_STATE_s {
57 UINT4 istate[4];
58 UINT4 ostate[4];
59} HMAC_MD5_STATE;
60
61/* One step hmac computation
62 *
63 * digest may be same as text or key
64 */
65void hmac_md5(const unsigned char *text, int text_len,
66 const unsigned char *key, int key_len,
67 unsigned char digest[HMAC_MD5_SIZE]);
68
69/* create context from key
70 */
71void hmac_md5_init(HMAC_MD5_CTX *hmac,
72 const unsigned char *key, int key_len);
73
74/* precalculate intermediate state from key
75 */
76void hmac_md5_precalc(HMAC_MD5_STATE *hmac,
77 const unsigned char *key, int key_len);
78
79/* initialize context from intermediate state
80 */
81void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state);
82
83#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len))
84
85/* finish hmac from intermediate result. Intermediate result is zeroed.
86 */
87void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
88 HMAC_MD5_CTX *hmac);
89
90#ifdef __cplusplus
91}
92#endif
93
94#endif /* HMAC_MD5_H */
diff --git a/libetpan/src/data-types/mail.h b/libetpan/src/data-types/mail.h
new file mode 100644
index 0000000..447aaf7
--- a/dev/null
+++ b/libetpan/src/data-types/mail.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_H
37
38#define MAIL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/data-types/mail_cache_db.c b/libetpan/src/data-types/mail_cache_db.c
new file mode 100644
index 0000000..0b73775
--- a/dev/null
+++ b/libetpan/src/data-types/mail_cache_db.c
@@ -0,0 +1,403 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mail_cache_db.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <stdlib.h>
42#include <string.h>
43
44#ifndef CONFIG_H
45#define CONFIG_H
46#include "config.h"
47#endif
48
49#include "libetpan-config.h"
50
51#include "maillock.h"
52
53#if DBVERS >= 1
54#include <db.h>
55#endif
56
57#if DBVERS >= 1
58static struct mail_cache_db * mail_cache_db_new(DB * db)
59{
60 struct mail_cache_db * cache_db;
61
62 cache_db = malloc(sizeof(* cache_db));
63 if (cache_db == NULL)
64 return NULL;
65 cache_db->internal_database = db;
66
67 return cache_db;
68}
69
70static void mail_cache_db_free(struct mail_cache_db * cache_db)
71{
72 free(cache_db);
73}
74#endif
75
76int mail_cache_db_open(const char * filename,
77 struct mail_cache_db ** pcache_db)
78{
79#if DBVERS >= 1
80 DB * dbp;
81 int r;
82 struct mail_cache_db * cache_db;
83
84#if DB_VERSION_MAJOR >= 3
85 r = db_create(&dbp, NULL, 0);
86 if (r != 0)
87 goto err;
88
89#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1))
90 r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE,
91 S_IRUSR | S_IWUSR);
92#else
93 r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR);
94#endif
95 if (r != 0)
96 goto close_db;
97#else
98#if DBVERS > 1
99 r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR,
100 NULL, NULL, &dbp);
101 if (r != 0)
102 goto err;
103#elif DBVERS == 1
104 dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL);
105 if (dbp == NULL)
106 goto err;
107#else
108 goto err;
109#endif
110#endif
111
112 cache_db = mail_cache_db_new(dbp);
113 if (cache_db == NULL)
114 goto close_db;
115
116 * pcache_db = cache_db;
117
118 return 0;
119
120 close_db:
121#if DBVERS > 1
122 dbp->close(dbp, 0);
123#elif DBVERS == 1
124 dbp->close(dbp);
125#endif
126 err:
127 return -1;
128#else
129 return -1;
130#endif
131}
132
133void mail_cache_db_close(struct mail_cache_db * cache_db)
134{
135#if DBVERS >= 1
136 DB * dbp;
137
138 dbp = cache_db->internal_database;
139
140#if DBVERS > 1
141 dbp->close(cache_db->internal_database, 0);
142#elif DBVERS == 1
143 dbp->close(cache_db->internal_database);
144#endif
145
146 mail_cache_db_free(cache_db);
147#endif
148}
149
150int mail_cache_db_open_lock(const char * filename,
151 struct mail_cache_db ** pcache_db)
152{
153 int r;
154 struct mail_cache_db * cache_db;
155
156 r = maillock_write_lock(filename, -1);
157 if (r < 0)
158 goto err;
159
160 r = mail_cache_db_open(filename, &cache_db);
161 if (r < 0)
162 goto unlock;
163
164 * pcache_db = cache_db;
165
166 return 0;
167
168 unlock:
169 maillock_write_unlock(filename, -1);
170 err:
171 return -1;
172}
173
174void mail_cache_db_close_unlock(const char * filename,
175 struct mail_cache_db * cache_db)
176{
177 maillock_write_unlock(filename, -1);
178 mail_cache_db_close(cache_db);
179}
180
181
182int mail_cache_db_put(struct mail_cache_db * cache_db,
183 const void * key, size_t key_len, const void * value, size_t value_len)
184{
185#if DBVERS >= 1
186 int r;
187 DBT db_key;
188 DBT db_data;
189 DB * dbp;
190
191 dbp = cache_db->internal_database;
192
193 memset(&db_key, 0, sizeof(db_key));
194 memset(&db_data, 0, sizeof(db_data));
195 db_key.data = (void *) key;
196 db_key.size = key_len;
197 db_data.data = (void *) value;
198 db_data.size = value_len;
199
200#if DBVERS > 1
201 r = dbp->put(dbp, NULL, &db_key, &db_data, 0);
202#elif DBVERS == 1
203 r = dbp->put(dbp, &db_key, &db_data, 0);
204#else
205 r = -1;
206#endif
207
208 return r;
209#else
210 return -1;
211#endif
212}
213
214int mail_cache_db_get(struct mail_cache_db * cache_db,
215 const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len)
216{
217#if DBVERS >= 1
218 int r;
219 DBT db_key;
220 DBT db_data;
221 DB * dbp;
222
223 dbp = cache_db->internal_database;
224
225 memset(&db_key, 0, sizeof(db_key));
226 memset(&db_data, 0, sizeof(db_data));
227 db_key.data = (void *) key;
228 db_key.size = key_len;
229
230#if DBVERS > 1
231 r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
232#elif DBVERS == 1
233 r = dbp->get(dbp, &db_key, &db_data, 0);
234#else
235 r = -1;
236#endif
237
238 if (r != 0)
239 return r;
240
241 * pvalue = db_data.data;
242 * pvalue_len = db_data.size;
243
244 return 0;
245#else
246 return -1;
247#endif
248}
249
250int mail_cache_db_del(struct mail_cache_db * cache_db,
251 const void * key, size_t key_len)
252{
253#if DBVERS >= 1
254 int r;
255 DBT db_key;
256 DB * dbp;
257
258 dbp = cache_db->internal_database;
259
260 memset(&db_key, 0, sizeof(db_key));
261 db_key.data = (void *) key;
262 db_key.size = key_len;
263
264#if DBVERS > 1
265 r = dbp->del(dbp, NULL, &db_key, 0);
266#elif DBVERS == 1
267 r = dbp->del(dbp, &db_key, 0);
268#else
269 r = -1;
270#endif
271
272 return r;
273#else
274 return -1;
275#endif
276}
277
278#if DBVERS > 1
279int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
280 chash * exist)
281{
282 DB * dbp;
283 int r;
284 DBC * dbcp;
285 DBT db_key;
286 DBT db_data;
287
288 dbp = cache_db->internal_database;
289
290 r = dbp->cursor(dbp, NULL, &dbcp, 0);
291 if (r != 0)
292 return r;
293
294 memset(&db_key, 0, sizeof(db_key));
295 memset(&db_data, 0, sizeof(db_data));
296
297 while (1) {
298 chashdatum hash_key;
299 chashdatum hash_data;
300
301 r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT);
302 if (r != 0)
303 break;
304
305 hash_key.data = db_key.data;
306 hash_key.len = db_key.size;
307
308 r = chash_get(exist, &hash_key, &hash_data);
309 if (r < 0) {
310 r = dbcp->c_del(dbcp, 0);
311 if (r != 0)
312 return r;
313 }
314 }
315
316 r = dbcp->c_close(dbcp);
317 if (r != 0)
318 return r;
319
320 return 0;
321}
322#elif DBVERS == 1
323int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
324 chash * exist)
325{
326 DB * dbp;
327 int r;
328 DBT db_key;
329 DBT db_data;
330
331 dbp = cache_db->internal_database;
332
333 r = dbp->seq(dbp, &db_key, &db_data, R_FIRST);
334 if (r == -1)
335 return r;
336
337 while (r == 0) {
338 chashdatum hash_key;
339 chashdatum hash_data;
340
341 hash_key.data = db_key.data;
342 hash_key.len = db_key.size;
343
344 r = chash_get(exist, &hash_key, &hash_data);
345 if (r < 0) {
346 r = dbp->del(dbp, &db_key, 0);
347 if (r != 0)
348 return r;
349 }
350
351 r = dbp->seq(dbp, &db_key, &db_data, R_NEXT);
352 if (r == -1)
353 return r;
354 }
355
356 return 0;
357}
358#else
359int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
360 chash * exist)
361{
362 return -1;
363}
364#endif
365
366int mail_cache_db_get_size(struct mail_cache_db * cache_db,
367 const void * key, size_t key_len, size_t * pvalue_len)
368{
369#if DBVERS >= 1
370 int r;
371 DBT db_key;
372 DBT db_data;
373 DB * dbp;
374
375 dbp = cache_db->internal_database;
376
377 memset(&db_key, 0, sizeof(db_key));
378 memset(&db_data, 0, sizeof(db_data));
379 db_key.data = (void *) key;
380 db_key.size = key_len;
381#if DBVERS > 1
382 db_data.flags = DB_DBT_USERMEM;
383 db_data.ulen = 0;
384#endif
385
386#if DBVERS > 1
387 r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
388#elif DBVERS == 1
389 r = dbp->get(dbp, &db_key, &db_data, 0);
390#else
391 r = -1;
392#endif
393
394 if (r != 0)
395 return r;
396
397 * pvalue_len = db_data.size;
398
399 return 0;
400#else
401 return -1;
402#endif
403}
diff --git a/libetpan/src/data-types/mail_cache_db.h b/libetpan/src/data-types/mail_cache_db.h
new file mode 100644
index 0000000..9ce915c
--- a/dev/null
+++ b/libetpan/src/data-types/mail_cache_db.h
@@ -0,0 +1,148 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_CACHE_DB_H
37
38#define MAIL_CACHE_DB_H
39
40#include <sys/types.h>
41#include "mail_cache_db_types.h"
42#include "chash.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/*
49 this module will handle a database "f(key) -> value" in a file
50
51 berkeley DB or other can be used for implementation of low-level file.
52*/
53
54/*
55 mail_cache_db_open()
56
57 This function opens the file "filename".
58 The pointer return in pcache_db should be used for further references
59 to the database.
60*/
61
62int mail_cache_db_open(const char * filename,
63 struct mail_cache_db ** pcache_db);
64
65/*
66 mail_cache_db_close()
67
68 This function closes the opened database.
69 The pointer cannot be used later.
70*/
71
72void mail_cache_db_close(struct mail_cache_db * cache_db);
73
74/*
75 mail_cache_db_open_lock()
76
77 This function opens and locks the file "filename".
78 The pointer return in pcache_db should be used for further references
79 to the database.
80*/
81
82int mail_cache_db_open_lock(const char * filename,
83 struct mail_cache_db ** pcache_db);
84
85/*
86 mail_cache_db_open_unlock()
87
88 This function closes and unlocks the opened database.
89 The pointer cannot be used later.
90*/
91
92void mail_cache_db_close_unlock(const char * filename,
93 struct mail_cache_db * cache_db);
94
95/*
96 mail_cache_db_put()
97
98 This function will store a given key and value in the database.
99*/
100
101int mail_cache_db_put(struct mail_cache_db * cache_db,
102 const void * key, size_t key_len, const void * value, size_t value_len);
103
104/*
105 mail_cache_db_get()
106
107 This function will retrieve the value corresponding to a given key
108 from the database.
109*/
110
111int mail_cache_db_get(struct mail_cache_db * cache_db,
112 const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len);
113
114/*
115 mail_cache_db_get_size()
116
117 This function will retrieve the size of the value corresponding
118 to a given key from the database.
119*/
120
121int mail_cache_db_get_size(struct mail_cache_db * cache_db,
122 const void * key, size_t key_len, size_t * pvalue_len);
123
124/*
125 mail_cache_db_del()
126
127 This function will delete the given key and the corresponding value
128 from the database.
129*/
130
131int mail_cache_db_del(struct mail_cache_db * cache_db,
132 const void * key, size_t key_len);
133
134/*
135 mail_cache_clean_up()
136
137 This function will delete the key all the key/value pairs of the
138 database file which key does not exist in the given hash.
139*/
140
141int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
142 chash * exist);
143
144#ifdef __cplusplus
145}
146#endif
147
148#endif
diff --git a/libetpan/src/data-types/mail_cache_db_types.h b/libetpan/src/data-types/mail_cache_db_types.h
new file mode 100644
index 0000000..aff77e5
--- a/dev/null
+++ b/libetpan/src/data-types/mail_cache_db_types.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_CACHE_DB_TYPES_H
37
38#define MAIL_CACHE_DB_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44struct mail_cache_db {
45 void * internal_database;
46};
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/data-types/maillock.c b/libetpan/src/data-types/maillock.c
new file mode 100644
index 0000000..b1741d0
--- a/dev/null
+++ b/libetpan/src/data-types/maillock.c
@@ -0,0 +1,301 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maillock.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <fcntl.h>
43#include <unistd.h>
44#include <stdio.h>
45#include <time.h>
46#include <string.h>
47#include "config.h"
48
49#ifdef HAVE_LIBLOCKFILE
50#include <lockfile.h>
51#endif
52
53/* ********************************************************************** */
54
55/* lock primitives */
56
57/* the lock code is modified from the dot lock file code from mail.local.c */
58
59/*
60 SENDMAIL LICENSE
61
62The following license terms and conditions apply, unless a different
63license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor,
64Emeryville, CA 94608, or by electronic mail at license@sendmail.com.
65
66License Terms:
67
68Use, Modification and Redistribution (including distribution of any
69modified or derived work) in source and binary forms is permitted only if
70each of the following conditions is met:
71
721. Redistributions qualify as "freeware" or "Open Source Software" under
73 one of the following terms:
74
75 (a) Redistributions are made at no charge beyond the reasonable cost of
76 materials and delivery.
77
78 (b) Redistributions are accompanied by a copy of the Source Code or by an
79 irrevocable offer to provide a copy of the Source Code for up to three
80 years at the cost of materials and delivery. Such redistributions
81 must allow further use, modification, and redistribution of the Source
82 Code under substantially the same terms as this license. For the
83 purposes of redistribution "Source Code" means the complete compilable
84 and linkable source code of sendmail including all modifications.
85
862. Redistributions of source code must retain the copyright notices as they
87 appear in each source code file, these license terms, and the
88 disclaimer/limitation of liability set forth as paragraph 6 below.
89
903. Redistributions in binary form must reproduce the Copyright Notice,
91 these license terms, and the disclaimer/limitation of liability set
92 forth as paragraph 6 below, in the documentation and/or other materials
93 provided with the distribution. For the purposes of binary distribution
94 the "Copyright Notice" refers to the following language:
95 "Copyright (c) 1998-2002 Sendmail, Inc. All rights reserved."
96
974. Neither the name of Sendmail, Inc. nor the University of California nor
98 the names of their contributors may be used to endorse or promote
99 products derived from this software without specific prior written
100 permission. The name "sendmail" is a trademark of Sendmail, Inc.
101
1025. All redistributions must comply with the conditions imposed by the
103 University of California on certain embedded code, whose copyright
104 notice and conditions for redistribution are as follows:
105
106 (a) Copyright (c) 1988, 1993 The Regents of the University of
107 California. All rights reserved.
108
109 (b) Redistribution and use in source and binary forms, with or without
110 modification, are permitted provided that the following conditions
111 are met:
112
113 (i) Redistributions of source code must retain the above copyright
114 notice, this list of conditions and the following disclaimer.
115
116 (ii) Redistributions in binary form must reproduce the above
117 copyright notice, this list of conditions and the following
118 disclaimer in the documentation and/or other materials provided
119 with the distribution.
120
121 (iii) Neither the name of the University nor the names of its
122 contributors may be used to endorse or promote products derived
123 from this software without specific prior written permission.
124
1256. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
126 SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
127 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
128 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
129 NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
130 CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
131 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
132 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
133 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
134 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
135 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
136 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
137*/
138
139/*
140 TODO : lock, prefer fcntl() over flock()
141 AND use dotlock code above
142*/
143
144 #define LOCKTO_RM 300/* timeout for stale lockfile removal */
145 #define LOCKTO_GLOB 400/* global timeout for lockfile creation */
146
147static int lock_common(const char * filename, int fd, short locktype)
148{
149 char lockfilename[PATH_MAX];
150 struct flock lock;
151 /* dot lock file */
152 int statfailed = 0;
153 time_t start;
154 int r;
155 int res;
156
157 /* dot lock file */
158
159 if (strlen(filename) + 6 > PATH_MAX) {
160 res = -1;
161 goto err;
162 }
163
164 snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
165
166#ifdef HAVE_LIBLOCKFILE
167 return lockfile_create(lockfilename, LOCKTO_GLOB, 0);
168#else
169
170 lock.l_start = 0;
171 lock.l_len = 0;
172 lock.l_pid = getpid();
173 lock.l_type = locktype;
174 lock.l_whence = SEEK_SET;
175
176 r = fcntl(fd, F_SETLKW, &lock);
177 if (r < 0) {
178 /* WARNING POSIX lock could not be applied */
179 }
180
181 time(&start);
182 while (1) {
183 int fd;
184 struct stat st;
185 time_t now;
186
187 /* global timeout */
188 time(&now);
189 if (now > start + LOCKTO_GLOB) {
190 res = -1;
191 goto unlock;
192 }
193
194 fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0);
195 if (fd >= 0) {
196 /* defeat lock checking programs which test pid */
197 write(fd, "0", 2);
198 close(fd);
199 break;
200 }
201
202 /* libEtPan! - adds a delay of 5 seconds between each tries */
203 sleep(5);
204
205 if (stat(lockfilename, &st) < 0) {
206 if (statfailed++ > 5) {
207 res = -1;
208 goto unlock;
209 }
210 continue;
211 }
212 statfailed = 0;
213 time(&now);
214
215 if (now < st.st_ctime + LOCKTO_RM)
216 continue;
217
218 /* try to remove stale lockfile */
219 if (unlink(lockfilename) < 0) {
220 res = -1;
221 goto unlock;
222 }
223
224 /*
225 libEtPan! - removes this delay of 5 seconds,
226 maybe it was misplaced ?
227 */
228#if 0
229 sleep(5);
230#endif
231 }
232
233 return 0;
234
235 unlock:
236 lock.l_start = 0;
237 lock.l_len = 0;
238 lock.l_pid = getpid();
239 lock.l_type = F_UNLCK;
240 lock.l_whence = SEEK_SET;
241
242 r = fcntl(fd, F_SETLK, &lock);
243 if (r < 0) {
244 /* WARNING POSIX lock could not be applied */
245 }
246#endif
247 err:
248 return res;
249}
250
251static int unlock_common(const char * filename, int fd)
252{
253 char lockfilename[PATH_MAX];
254 struct flock lock;
255 int r;
256
257 if (strlen(filename) + 6 > PATH_MAX)
258 return -1;
259
260 snprintf(lockfilename, PATH_MAX, "%s.lock", filename);
261
262#ifdef HAVE_LIBLOCKFILE
263 return lockfile_remove(lockfilename);
264#else
265
266 unlink(lockfilename);
267
268 lock.l_start = 0;
269 lock.l_len = 0;
270 lock.l_pid = getpid();
271 lock.l_type = F_UNLCK;
272 lock.l_whence = SEEK_SET;
273
274 r = fcntl(fd, F_SETLK, &lock);
275 if (r < 0) {
276 /* WARNING POSIX lock could not be applied */
277 }
278
279 return 0;
280#endif
281}
282
283int maillock_read_lock(const char * filename, int fd)
284{
285 return lock_common(filename, fd, F_RDLCK);
286}
287
288int maillock_read_unlock(const char * filename, int fd)
289{
290 return unlock_common(filename, fd);
291}
292
293int maillock_write_lock(const char * filename, int fd)
294{
295 return lock_common(filename, fd, F_WRLCK);
296}
297
298int maillock_write_unlock(const char * filename, int fd)
299{
300 return unlock_common(filename, fd);
301}
diff --git a/libetpan/src/data-types/maillock.h b/libetpan/src/data-types/maillock.h
new file mode 100644
index 0000000..8d166c6
--- a/dev/null
+++ b/libetpan/src/data-types/maillock.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILLOCK_H
37
38#define MAILLOCK_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44int maillock_read_lock(const char * filename, int fd);
45int maillock_read_unlock(const char * filename, int fd);
46int maillock_write_lock(const char * filename, int fd);
47int maillock_write_unlock(const char * filename, int fd);
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/src/data-types/mailsem.c b/libetpan/src/data-types/mailsem.c
new file mode 100644
index 0000000..383d953
--- a/dev/null
+++ b/libetpan/src/data-types/mailsem.c
@@ -0,0 +1,114 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsem.h"
37#include <semaphore.h>
38#include <stdlib.h>
39#include <stdio.h>
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <fcntl.h>
43
44enum {
45 SEMKIND_SEMOPEN,
46 SEMKIND_SEMINIT,
47};
48
49#define SEMNAME_LEN 64
50
51struct mailsem * mailsem_new(void)
52{
53 struct mailsem * sem;
54 int r;
55
56 sem = malloc(sizeof(* sem));
57 if (sem == NULL)
58 goto err;
59
60 r = sem_init(sem->sem_sem, 0, 0);
61 if (r < 0) {
62 char name[SEMNAME_LEN];
63
64 free(sem->sem_sem);
65
66 snprintf(name, sizeof(name), "sem-%p", sem);
67
68#ifndef __CYGWIN__
69 sem->sem_sem = sem_open(name, O_CREAT, 0600, 0);
70 if (sem->sem_sem == NULL)
71 goto err;
72
73 sem->sem_kind = SEMKIND_SEMOPEN;
74#else
75 goto err;
76#endif
77 }
78 else {
79 sem->sem_kind = SEMKIND_SEMINIT;
80 }
81
82 return sem;
83
84 err:
85 return NULL;
86}
87
88void mailsem_free(struct mailsem * sem)
89{
90 if (sem->sem_kind == SEMKIND_SEMOPEN) {
91 char name[SEMNAME_LEN];
92
93#ifndef __CYGWIN__
94 sem_close((sem_t *) sem->sem_sem);
95 snprintf(name, sizeof(name), "sem-%p", sem);
96 sem_unlink(name);
97#endif
98 }
99 else {
100 sem_destroy((sem_t *) sem->sem_sem);
101 free(sem->sem_sem);
102 }
103 free(sem);
104}
105
106int mailsem_up(struct mailsem * sem)
107{
108 return sem_wait((sem_t *) sem->sem_sem);
109}
110
111int mailsem_down(struct mailsem * sem)
112{
113 return sem_post((sem_t *) sem->sem_sem);
114}
diff --git a/libetpan/src/data-types/mailsem.h b/libetpan/src/data-types/mailsem.h
new file mode 100644
index 0000000..3a6d7bc
--- a/dev/null
+++ b/libetpan/src/data-types/mailsem.h
@@ -0,0 +1,51 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSEM_H
37
38#define MAILSEM_H
39
40struct mailsem {
41 void * sem_sem;
42 int sem_kind;
43};
44
45struct mailsem * mailsem_new(void);
46void mailsem_free(struct mailsem * sem);
47
48int mailsem_up(struct mailsem * sem);
49int mailsem_down(struct mailsem * sem);
50
51#endif
diff --git a/libetpan/src/data-types/mailstream.c b/libetpan/src/data-types/mailstream.c
new file mode 100644
index 0000000..ceb0ced
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream.c
@@ -0,0 +1,399 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream.h"
37#include "maillock.h"
38#include <string.h>
39#include <stdlib.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42
43#define DEFAULT_NETWORK_TIMEOUT 300
44
45#if 0
46#ifdef LIBETPAN_MAILSTREAM_DEBUG
47
48#define STREAM_DEBUG
49
50#include <stdio.h>
51
52#define LOG_FILE "libetpan-stream-debug.log"
53
54int mailstream_debug = 0;
55
56#define STREAM_LOG_BUF(buf, size) \
57 if (mailstream_debug) { \
58 FILE * f; \
59 mode_t old_mask; \
60 \
61 old_mask = umask(0077); \
62 f = fopen(LOG_FILE, "a"); \
63 umask(old_mask); \
64 if (f != NULL) { \
65 maillock_write_lock(LOG_FILE, fileno(f)); \
66 fwrite((buf), 1, (size), f); \
67 maillock_write_unlock(LOG_FILE, fileno(f)); \
68 fclose(f); \
69 } \
70 }
71
72#define STREAM_LOG(str) \
73 if (mailstream_debug) { \
74 FILE * f; \
75 mode_t old_mask; \
76 \
77 old_mask = umask(0077); \
78 f = fopen(LOG_FILE, "a"); \
79 umask(old_mask); \
80 if (f != NULL) { \
81 maillock_write_lock(LOG_FILE, fileno(f)); \
82 fputs((str), f); \
83 maillock_write_unlock(LOG_FILE, fileno(f)); \
84 fclose(f); \
85 } \
86 }
87
88#else
89
90#define STREAM_LOG_BUF(buf, size) do { } while (0)
91#define STREAM_LOG(buf) do { } while (0)
92
93#endif
94#endif
95
96#define STREAM_LOG_BUF(buf, size) do { } while (0)
97#define STREAM_LOG(buf) do { } while (0)
98
99
100mailstream * mailstream_new(mailstream_low * low, size_t buffer_size)
101{
102 mailstream * s;
103
104 s = malloc(sizeof(* s));
105 if (s == NULL)
106 goto err;
107
108 s->read_buffer = malloc(buffer_size);
109 if (s->read_buffer == NULL)
110 goto free_s;
111 s->read_buffer_len = 0;
112
113 s->write_buffer = malloc(buffer_size);
114 if (s->write_buffer == NULL)
115 goto free_read_buffer;
116 s->write_buffer_len = 0;
117
118 s->buffer_max_size = buffer_size;
119 s->low = low;
120
121 return s;
122
123 free_read_buffer:
124 free(s->read_buffer);
125 free_s:
126 free(s);
127 err:
128 return NULL;
129}
130
131static size_t write_to_internal_buffer(mailstream * s,
132 const void * buf, size_t count)
133{
134 memcpy(s->write_buffer + s->write_buffer_len, buf, count);
135 s->write_buffer_len += count;
136
137 return count;
138}
139
140static size_t write_direct(mailstream * s, const void * buf, size_t count)
141{
142 size_t left;
143 const char * cur_buf;
144 ssize_t written;
145
146 cur_buf = buf;
147 left = count;
148 while (left > 0) {
149 written = mailstream_low_write(s->low, cur_buf, left);
150
151 if (written == -1) {
152 if (count == left)
153 return -1;
154 else
155 return count - left;
156 }
157
158 cur_buf += written;
159 left -= written;
160 }
161
162 return count;
163}
164
165ssize_t mailstream_write(mailstream * s, const void * buf, size_t count)
166{
167 int r;
168
169 if (s == NULL)
170 return -1;
171
172 if (count + s->write_buffer_len > s->buffer_max_size) {
173 r = mailstream_flush(s);
174 if (r == -1)
175 return -1;
176
177 if (count > s->buffer_max_size)
178 return write_direct(s, buf, count);
179 }
180
181#ifdef STREAM_DEBUG
182 STREAM_LOG(">>>>>>> send >>>>>>\n");
183 STREAM_LOG_BUF(buf, count);
184 STREAM_LOG("\n");
185 STREAM_LOG(">>>>>>> end send >>>>>>\n");
186#endif
187
188 return write_to_internal_buffer(s, buf, count);
189}
190
191int mailstream_flush(mailstream * s)
192{
193 char * cur_buf;
194 size_t left;
195 ssize_t written;
196
197 if (s == NULL)
198 return -1;
199
200 cur_buf = s->write_buffer;
201 left = s->write_buffer_len;
202 while (left > 0) {
203 written = mailstream_low_write(s->low, cur_buf, left);
204
205 if (written == -1)
206 goto move_buffer;
207 cur_buf += written;
208 left -= written;
209 }
210
211 s->write_buffer_len = 0;
212
213 return 0;
214
215 move_buffer:
216 memmove(s->write_buffer, cur_buf, left);
217 s->write_buffer_len = left;
218 return -1;
219}
220
221static ssize_t read_from_internal_buffer(mailstream * s,
222 void * buf, size_t count)
223{
224 if (count >= s->read_buffer_len)
225 count = s->read_buffer_len;
226 if (count != 0)
227 memcpy(buf, s->read_buffer, count);
228
229 s->read_buffer_len -= count;
230 if (s->read_buffer_len != 0)
231 memmove(s->read_buffer, s->read_buffer + count,
232 s->read_buffer_len);
233
234 return count;
235}
236
237static ssize_t read_through_buffer(mailstream * s, void * buf, size_t count)
238{
239 size_t left;
240 char * cur_buf;
241 ssize_t bytes_read;
242
243 cur_buf = buf;
244 left = count;
245
246 while (left > 0) {
247 bytes_read = mailstream_low_read(s->low, cur_buf, left);
248
249 if (bytes_read == -1) {
250 if (count == left)
251 return -1;
252 else
253 return count - left;
254 }
255 else if (bytes_read == 0)
256 return count - left;
257
258 cur_buf += bytes_read;
259 left -= bytes_read;
260 }
261
262 return count;
263}
264
265ssize_t mailstream_read(mailstream * s, void * buf, size_t count)
266{
267 ssize_t read_bytes;
268 char * cur_buf;
269 size_t left;
270
271 if (s == NULL)
272 return -1;
273
274 left = count;
275 cur_buf = buf;
276 read_bytes = read_from_internal_buffer(s, cur_buf, left);
277 cur_buf += read_bytes;
278 left -= read_bytes;
279
280 if (left == 0) {
281#ifdef STREAM_DEBUG
282 STREAM_LOG("<<<<<<< read <<<<<<\n");
283 STREAM_LOG_BUF(buf, read_bytes);
284 STREAM_LOG("\n");
285 STREAM_LOG("<<<<<<< end read <<<<<<\n");
286#endif
287
288 return read_bytes;
289 }
290
291 if (left > s->buffer_max_size) {
292 read_bytes = read_through_buffer(s, cur_buf, left);
293 if (read_bytes == -1) {
294 if (count == left)
295 return -1;
296 else {
297
298#ifdef STREAM_DEBUG
299 STREAM_LOG("<<<<<<< read <<<<<<\n");
300 STREAM_LOG_BUF(buf, count - left);
301 STREAM_LOG("\n");
302 STREAM_LOG("<<<<<<< end read <<<<<<\n");
303#endif
304
305 return count - left;
306 }
307 }
308
309 cur_buf += read_bytes;
310 left -= read_bytes;
311
312#ifdef STREAM_DEBUG
313 STREAM_LOG("<<<<<<< read <<<<<<\n");
314 STREAM_LOG_BUF(buf, count - left);
315 STREAM_LOG("\n");
316 STREAM_LOG("<<<<<<< end read <<<<<<\n");
317#endif
318
319 return count - left;
320 }
321
322 read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size);
323 if (read_bytes == -1) {
324 if (left == count)
325 return -1;
326 else {
327#ifdef STREAM_DEBUG
328 STREAM_LOG("<<<<<<< read <<<<<<\n");
329 STREAM_LOG_BUF(buf, count - left);
330 STREAM_LOG("\n");
331 STREAM_LOG("<<<<<<< end read <<<<<<\n");
332#endif
333
334 return count - left;
335 }
336 }
337 else
338 s->read_buffer_len += read_bytes;
339
340 read_bytes = read_from_internal_buffer(s, cur_buf, left);
341 cur_buf += read_bytes;
342 left -= read_bytes;
343
344#ifdef STREAM_DEBUG
345 STREAM_LOG("<<<<<<< read <<<<<<\n");
346 STREAM_LOG_BUF(buf, count - left);
347 STREAM_LOG("\n");
348 STREAM_LOG("<<<<<<< end read <<<<<<\n");
349#endif
350
351 return count - left;
352}
353
354mailstream_low * mailstream_get_low(mailstream * s)
355{
356 return s->low;
357}
358
359void mailstream_set_low(mailstream * s, mailstream_low * low)
360{
361 s->low = low;
362}
363
364int mailstream_close(mailstream * s)
365{
366 mailstream_low_close(s->low);
367 mailstream_low_free(s->low);
368
369 free(s->read_buffer);
370 free(s->write_buffer);
371
372 free(s);
373
374 return 0;
375}
376
377
378
379ssize_t mailstream_feed_read_buffer(mailstream * s)
380{
381 ssize_t read_bytes;
382
383 if (s == NULL)
384 return -1;
385
386 if (s->read_buffer_len == 0) {
387 read_bytes = mailstream_low_read(s->low, s->read_buffer,
388 s->buffer_max_size);
389 if (read_bytes == -1)
390 return -1;
391 s->read_buffer_len += read_bytes;
392 }
393
394 return s->read_buffer_len;
395}
396
397struct timeval mailstream_network_delay =
398 { .tv_sec = DEFAULT_NETWORK_TIMEOUT, .tv_usec = 0 };
399
diff --git a/libetpan/src/data-types/mailstream.h b/libetpan/src/data-types/mailstream.h
new file mode 100644
index 0000000..04a5ae3
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_H
37
38#define MAILSTREAM_H
39
40#include <sys/time.h>
41
42#include <libetpan/mailstream_low.h>
43#include <libetpan/mailstream_helper.h>
44#include <libetpan/mailstream_socket.h>
45#include <libetpan/mailstream_ssl.h>
46#include <libetpan/mailstream_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52mailstream * mailstream_new(mailstream_low * low, size_t buffer_size);
53ssize_t mailstream_write(mailstream * s, const void * buf, size_t count);
54ssize_t mailstream_read(mailstream * s, void * buf, size_t count);
55int mailstream_close(mailstream * s);
56int mailstream_flush(mailstream * s);
57ssize_t mailstream_feed_read_buffer(mailstream * s);
58mailstream_low * mailstream_get_low(mailstream * s);
59void mailstream_set_low(mailstream * s, mailstream_low * low);
60
61#ifdef LIBETPAN_MAILSTREAM_DEBUG
62extern int mailstream_debug;
63#endif
64
65#define LIBETPAN_MAILSTREAM_NETWORK_DELAY
66extern struct timeval mailstream_network_delay;
67
68#ifdef __cplusplus
69}
70#endif
71
72#endif
73
diff --git a/libetpan/src/data-types/mailstream_helper.c b/libetpan/src/data-types/mailstream_helper.c
new file mode 100644
index 0000000..2f0b9ae
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_helper.c
@@ -0,0 +1,515 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream_helper.h"
37#include <string.h>
38#include <stdio.h>
39#include "mail.h"
40
41static void remove_trailing_eol(MMAPString * mmapstr)
42{
43 if (mmapstr->str[mmapstr->len - 1] == '\n') {
44 mmapstr->len --;
45 mmapstr->str[mmapstr->len] = '\0';
46 }
47 if (mmapstr->str[mmapstr->len - 1] == '\r') {
48 mmapstr->len --;
49 mmapstr->str[mmapstr->len] = '\0';
50 }
51}
52
53char * mailstream_read_line(mailstream * stream, MMAPString * line)
54{
55 if (mmap_string_assign(line, "") == NULL)
56 return NULL;
57
58 return mailstream_read_line_append(stream, line);
59}
60
61static char * mailstream_read_len_append(mailstream * stream,
62 MMAPString * line,
63 size_t i)
64{
65 size_t cur_size;
66
67 cur_size = line->len;
68 if (mmap_string_set_size(line, line->len + i) == NULL)
69 return NULL;
70 if (mailstream_read(stream, line->str + cur_size, i) < 0)
71 return NULL;
72 return line->str;
73}
74
75char * mailstream_read_line_append(mailstream * stream, MMAPString * line)
76{
77 if (stream == NULL)
78 return NULL;
79
80 do {
81 if (stream->read_buffer_len > 0) {
82 size_t i;
83
84 i = 0;
85 while (i < stream->read_buffer_len) {
86 if (stream->read_buffer[i] == '\n')
87 return mailstream_read_len_append(stream, line, i + 1);
88 i++;
89 }
90 if (mailstream_read_len_append(stream, line,
91 stream->read_buffer_len) == NULL)
92 return NULL;
93 }
94 else {
95 ssize_t r;
96
97 r = mailstream_feed_read_buffer(stream);
98 if (r == -1)
99 return NULL;
100
101 if (r == 0)
102 break;
103 }
104 }
105 while (1);
106
107 return line->str;
108}
109
110char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line)
111{
112 if (!mailstream_read_line(stream, line))
113 return NULL;
114
115 remove_trailing_eol(line);
116
117 return line->str;
118}
119
120int mailstream_is_end_multiline(const char * line)
121{
122 if (line[0] != '.')
123 return FALSE;
124 if (line[1] != 0)
125 return FALSE;
126 return TRUE;
127}
128
129#if 1
130char * mailstream_read_multiline(mailstream * s, size_t size,
131 MMAPString * stream_buffer,
132 MMAPString * multiline_buffer,
133 size_t progr_rate,
134 progress_function * progr_fun)
135{
136 size_t count;
137 char * line;
138 size_t last;
139
140 if (mmap_string_assign(multiline_buffer, "") == NULL)
141 return NULL;
142
143 count = 0;
144 last = 0;
145
146 while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) {
147 if (mailstream_is_end_multiline(line))
148 return multiline_buffer->str;
149
150 if (line[0] == '.') {
151 if (mmap_string_append(multiline_buffer, line + 1) == NULL)
152 return NULL;
153 }
154 else {
155 if (mmap_string_append(multiline_buffer, line) == NULL)
156 return NULL;
157 }
158 if (mmap_string_append(multiline_buffer, "\r\n") == NULL)
159 return NULL;
160
161 count += strlen(line);
162 if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL))
163 if (count - last >= progr_rate) {
164 (* progr_fun)(count, size);
165 last = count;
166 }
167 }
168
169 return NULL;
170}
171
172#else
173
174/*
175 high speed but don't replace the line break with '\n' and neither
176 remove the '.'
177*/
178
179static gboolean end_of_multiline(const char * str, gint len)
180{
181 gint index;
182
183 index = len - 1;
184
185 if (str[index] != '\n')
186 return FALSE;
187 if (index == 0)
188 return FALSE;
189
190 index --;
191
192 if (str[index] == '\r') {
193 index --;
194 if (index == 0)
195 return FALSE;
196 }
197
198 if (str[index] != '.')
199 return FALSE;
200 if (index == 0)
201 return FALSE;
202
203 index--;
204
205 if (str[index] != '\n')
206 return FALSE;
207
208 return TRUE;
209}
210
211char * mailstream_read_multiline(mailstream * stream, size_t size,
212 MMAPString * stream_buffer,
213 MMAPString * line,
214 size_t progr_rate,
215 progress_function * progr_fun)
216{
217 if (stream == NULL)
218 return NULL;
219
220 mmap_string_assign(line, "");
221
222 do {
223 if (stream->read_buffer_len > 0) {
224 size_t i;
225
226 i = 0;
227 while (i < stream->read_buffer_len) {
228 if (end_of_multiline(stream->read_buffer, i + 1))
229 return mailstream_read_len_append(stream, line, i + 1);
230 i++;
231 }
232 if (mailstream_read_len_append(stream, line,
233 stream->read_buffer_len) == NULL)
234 return NULL;
235 if (end_of_multiline(line->str, line->len))
236 return line->str;
237 }
238 else
239 if (mailstream_feed_read_buffer(stream) == -1)
240 return NULL;
241 }
242 while (1);
243
244 return line->str;
245}
246#endif
247
248
249
250static inline ssize_t send_data_line(mailstream * s,
251 const char * line, size_t length)
252{
253 int fix_eol;
254 const char * start;
255 size_t count;
256
257 start = line;
258
259 fix_eol = 0;
260 count = 0;
261
262 while (1) {
263 if (length == 0)
264 break;
265
266 if (* line == '\r') {
267 line ++;
268
269 count ++;
270 length --;
271
272 if (length == 0) {
273 fix_eol = 1;
274 break;
275 }
276
277 if (* line == '\n') {
278 line ++;
279
280 count ++;
281 length --;
282
283 break;
284 }
285 else {
286 fix_eol = 1;
287 break;
288 }
289 }
290 else if (* line == '\n') {
291 line ++;
292
293 count ++;
294 length --;
295
296 fix_eol = 1;
297 break;
298 }
299
300 line ++;
301 length --;
302 count ++;
303 }
304
305 if (fix_eol) {
306 if (mailstream_write(s, start, count - 1) == -1)
307 goto err;
308 if (mailstream_write(s, "\r\n", 2) == -1)
309 goto err;
310 }
311 else {
312 if (mailstream_write(s, start, count) == -1)
313 goto err;
314 }
315
316
317#if 0
318 while (* line != '\n') {
319 if (* line == '\r')
320 pos = line;
321 if (* line == '\0')
322 return line;
323 if (mailstream_write(s, line, 1) == -1)
324 goto err;
325 line ++;
326 }
327 if (pos + 1 == line) {
328 if (mailstream_write(s, line, 1) == -1)
329 goto err;
330 }
331 else {
332 if (mailstream_write(s, "\r\n", 2) == -1)
333 goto err;
334 }
335 line ++;
336#endif
337
338 return count;
339
340 err:
341 return -1;
342}
343
344static inline int send_data_crlf(mailstream * s, const char * message,
345 size_t size,
346 int quoted,
347 size_t progr_rate,
348 progress_function * progr_fun)
349{
350 const char * current;
351 size_t count;
352 size_t last;
353 size_t remaining;
354
355 count = 0;
356 last = 0;
357
358 current = message;
359 remaining = size;
360
361 while (remaining > 0) {
362 ssize_t length;
363
364 if (quoted) {
365 if (current[0] == '.')
366 if (mailstream_write(s, ".", 1) == -1)
367 goto err;
368 }
369
370 length = send_data_line(s, current, remaining);
371 if (length < 0)
372 goto err;
373
374 current += length;
375
376 count += length;
377 if ((progr_rate != 0) && (progr_fun != NULL))
378 if (count - last >= progr_rate) {
379 (* progr_fun)(count, size);
380 last = count;
381 }
382
383 remaining -= length;
384 }
385
386 return 0;
387
388 err:
389 return -1;
390}
391
392int mailstream_send_data_crlf(mailstream * s, const char * message,
393 size_t size,
394 size_t progr_rate,
395 progress_function * progr_fun)
396{
397 return send_data_crlf(s, message, size, 0, progr_rate, progr_fun);
398}
399
400int mailstream_send_data(mailstream * s, const char * message,
401 size_t size,
402 size_t progr_rate,
403 progress_function * progr_fun)
404{
405 if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1)
406 goto err;
407
408 if (mailstream_write(s, "\r\n.\r\n", 5) == -1)
409 goto err;
410
411 if (mailstream_flush(s) == -1)
412 goto err;
413
414 return 0;
415
416 err:
417 return -1;
418}
419
420static inline ssize_t get_data_size(const char * line, size_t length,
421 size_t * result)
422{
423 int fix_eol;
424 const char * start;
425 size_t count;
426 size_t fixed_count;
427
428 start = line;
429
430 fix_eol = 0;
431 count = 0;
432 fixed_count = 0;
433
434 while (1) {
435 if (length == 0)
436 break;
437
438 if (* line == '\r') {
439 line ++;
440
441 count ++;
442 length --;
443
444 if (length == 0) {
445 fix_eol = 1;
446 fixed_count ++;
447 break;
448 }
449
450 if (* line == '\n') {
451 line ++;
452
453 count ++;
454 length --;
455
456 break;
457 }
458 else {
459 fix_eol = 1;
460 fixed_count ++;
461 break;
462 }
463 }
464 else if (* line == '\n') {
465 line ++;
466
467 count ++;
468 length --;
469
470 fix_eol = 1;
471 fixed_count ++;
472 break;
473 }
474
475 line ++;
476 length --;
477 count ++;
478 }
479
480 * result = count + fixed_count;
481
482 return count;
483}
484
485size_t mailstream_get_data_crlf_size(const char * message, size_t size)
486{
487 const char * current;
488 size_t count;
489 size_t last;
490 size_t remaining;
491 size_t fixed_count;
492
493 count = 0;
494 last = 0;
495 fixed_count = 0;
496
497 current = message;
498 remaining = size;
499
500 while (remaining > 0) {
501 ssize_t length;
502 size_t line_count;
503
504 length = get_data_size(current, remaining, &line_count);
505
506 fixed_count += line_count;
507 current += length;
508
509 count += length;
510
511 remaining -= length;
512 }
513
514 return fixed_count;
515}
diff --git a/libetpan/src/data-types/mailstream_helper.h b/libetpan/src/data-types/mailstream_helper.h
new file mode 100644
index 0000000..1bc36a2
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_helper.h
@@ -0,0 +1,77 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_HELPER_H
37
38#define MAILSTREAM_HELPER_H
39
40#include <libetpan/mmapstring.h>
41#include <libetpan/mailstream.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47char * mailstream_read_line(mailstream * stream, MMAPString * line);
48
49char * mailstream_read_line_append(mailstream * stream, MMAPString * line);
50
51char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line);
52
53char * mailstream_read_multiline(mailstream * s, size_t size,
54 MMAPString * stream_buffer,
55 MMAPString * multiline_buffer,
56 size_t progr_rate,
57 progress_function * progr_fun);
58
59int mailstream_is_end_multiline(const char * line);
60
61int mailstream_send_data_crlf(mailstream * s, const char * message,
62 size_t size,
63 size_t progr_rate,
64 progress_function * progr_fun);
65
66int mailstream_send_data(mailstream * s, const char * message,
67 size_t size,
68 size_t progr_rate,
69 progress_function * progr_fun);
70
71size_t mailstream_get_data_crlf_size(const char * message, size_t size);
72
73#ifdef __cplusplus
74}
75#endif
76
77#endif
diff --git a/libetpan/src/data-types/mailstream_low.c b/libetpan/src/data-types/mailstream_low.c
new file mode 100644
index 0000000..ab268bb
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_low.c
@@ -0,0 +1,164 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream_low.h"
37#include <stdlib.h>
38
39#ifdef LIBETPAN_MAILSTREAM_DEBUG
40
41#define STREAM_DEBUG
42
43#include <stdio.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include "maillock.h"
47
48#define LOG_FILE "libetpan-stream-debug.log"
49
50int mailstream_debug = 0;
51
52#define STREAM_LOG_BUF(buf, size) \
53 if (mailstream_debug) { \
54 FILE * f; \
55 mode_t old_mask; \
56 \
57 old_mask = umask(0077); \
58 f = fopen(LOG_FILE, "a"); \
59 umask(old_mask); \
60 if (f != NULL) { \
61 maillock_write_lock(LOG_FILE, fileno(f)); \
62 fwrite((buf), 1, (size), f); \
63 maillock_write_unlock(LOG_FILE, fileno(f)); \
64 fclose(f); \
65 } \
66 }
67
68#define STREAM_LOG(str) \
69 if (mailstream_debug) { \
70 FILE * f; \
71 mode_t old_mask; \
72 \
73 old_mask = umask(0077); \
74 f = fopen(LOG_FILE, "a"); \
75 umask(old_mask); \
76 if (f != NULL) { \
77 maillock_write_lock(LOG_FILE, fileno(f)); \
78 fputs((str), f); \
79 maillock_write_unlock(LOG_FILE, fileno(f)); \
80 fclose(f); \
81 } \
82 }
83
84#else
85
86#define STREAM_LOG_BUF(buf, size) do { } while (0)
87#define STREAM_LOG(buf) do { } while (0)
88
89#endif
90
91
92/* general functions */
93
94mailstream_low * mailstream_low_new(void * data,
95 mailstream_low_driver * driver)
96{
97 mailstream_low * s;
98
99 s = malloc(sizeof(* s));
100 if (s == NULL)
101 return NULL;
102
103 s->data = data;
104 s->driver = driver;
105
106 return s;
107}
108
109int mailstream_low_close(mailstream_low * s)
110{
111 if (s == NULL)
112 return -1;
113 s->driver->mailstream_close(s);
114
115 return 0;
116}
117
118int mailstream_low_get_fd(mailstream_low * s)
119{
120 if (s == NULL)
121 return -1;
122 return s->driver->mailstream_get_fd(s);
123}
124
125void mailstream_low_free(mailstream_low * s)
126{
127 s->driver->mailstream_free(s);
128}
129
130ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count)
131{
132 ssize_t r;
133
134 if (s == NULL)
135 return -1;
136 r = s->driver->mailstream_read(s, buf, count);
137
138#ifdef STREAM_DEBUG
139 if (r > 0) {
140 STREAM_LOG("<<<<<<< read <<<<<<\n");
141 STREAM_LOG_BUF(buf, r);
142 STREAM_LOG("\n");
143 STREAM_LOG("<<<<<<< end read <<<<<<\n");
144 }
145#endif
146
147 return r;
148}
149
150ssize_t mailstream_low_write(mailstream_low * s,
151 const void * buf, size_t count)
152{
153 if (s == NULL)
154 return -1;
155
156#ifdef STREAM_DEBUG
157 STREAM_LOG(">>>>>>> send >>>>>>\n");
158 STREAM_LOG_BUF(buf, count);
159 STREAM_LOG("\n");
160 STREAM_LOG(">>>>>>> end send >>>>>>\n");
161#endif
162
163 return s->driver->mailstream_write(s, buf, count);
164}
diff --git a/libetpan/src/data-types/mailstream_low.h b/libetpan/src/data-types/mailstream_low.h
new file mode 100644
index 0000000..e3fff1f
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_low.h
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_LOW_H
37
38#define MAILSTREAM_LOW_H
39
40#include <sys/types.h>
41#include <libetpan/mailstream_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* general functions */
48
49mailstream_low * mailstream_low_new(void * data,
50 mailstream_low_driver * driver);
51ssize_t mailstream_low_write(mailstream_low * s,
52 const void * buf, size_t count);
53ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count);
54int mailstream_low_close(mailstream_low * s);
55int mailstream_low_get_fd(mailstream_low * s);
56void mailstream_low_free(mailstream_low * s);
57
58#ifdef __cplusplus
59}
60#endif
61
62#endif
diff --git a/libetpan/src/data-types/mailstream_socket.c b/libetpan/src/data-types/mailstream_socket.c
new file mode 100644
index 0000000..bd58571
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_socket.c
@@ -0,0 +1,238 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream_socket.h"
37#include <unistd.h>
38#include <stdlib.h>
39#include <fcntl.h>
40#include <sys/socket.h>
41
42/*
43 these 3 headers MUST be included before <sys/select.h>
44 to insure compatibility with Mac OS X (this is true for 10.2)
45*/
46#include <sys/time.h>
47#include <sys/types.h>
48#include <unistd.h>
49#include <sys/select.h>
50
51/* mailstream_low, socket */
52
53static int mailstream_low_socket_close(mailstream_low * s);
54static ssize_t mailstream_low_socket_read(mailstream_low * s,
55 void * buf, size_t count);
56static ssize_t mailstream_low_socket_write(mailstream_low * s,
57 const void * buf, size_t count);
58static void mailstream_low_socket_free(mailstream_low * s);
59static int mailstream_low_socket_get_fd(mailstream_low * s);
60
61static mailstream_low_driver local_mailstream_socket_driver = {
62 mailstream_read: mailstream_low_socket_read,
63 mailstream_write: mailstream_low_socket_write,
64 mailstream_close: mailstream_low_socket_close,
65 mailstream_free: mailstream_low_socket_free,
66 mailstream_get_fd: mailstream_low_socket_get_fd,
67};
68
69mailstream_low_driver * mailstream_socket_driver =
70&local_mailstream_socket_driver;
71
72/* file descriptor must be given in (default) blocking-mode */
73
74static struct mailstream_socket_data * socket_data_new(int fd)
75{
76 struct mailstream_socket_data * socket_data;
77
78 socket_data = malloc(sizeof(* socket_data));
79 if (socket_data == NULL)
80 goto err;
81
82 socket_data->fd = fd;
83
84 return socket_data;
85
86 err:
87 return NULL;
88}
89
90static void socket_data_free(struct mailstream_socket_data * socket_data)
91{
92 free(socket_data);
93}
94
95static void socket_data_close(struct mailstream_socket_data * socket_data)
96{
97 close(socket_data->fd);
98 socket_data->fd = -1;
99}
100
101mailstream_low * mailstream_low_socket_open(int fd)
102{
103 mailstream_low * s;
104 struct mailstream_socket_data * socket_data;
105
106 socket_data = socket_data_new(fd);
107 if (socket_data == NULL)
108 goto err;
109
110 s = mailstream_low_new(socket_data, mailstream_socket_driver);
111 if (s == NULL)
112 goto free_socket_data;
113
114 return s;
115
116 free_socket_data:
117 socket_data_free(socket_data);
118 err:
119 return NULL;
120}
121
122static int mailstream_low_socket_close(mailstream_low * s)
123{
124 struct mailstream_socket_data * socket_data;
125
126 socket_data = (struct mailstream_socket_data *) s->data;
127 socket_data_close(socket_data);
128
129 return 0;
130}
131
132static void mailstream_low_socket_free(mailstream_low * s)
133{
134 struct mailstream_socket_data * socket_data;
135
136 socket_data = (struct mailstream_socket_data *) s->data;
137 socket_data_free(socket_data);
138 s->data = NULL;
139
140 free(s);
141}
142
143static int mailstream_low_socket_get_fd(mailstream_low * s)
144{
145 struct mailstream_socket_data * socket_data;
146
147 socket_data = (struct mailstream_socket_data *) s->data;
148 return socket_data->fd;
149}
150
151
152static ssize_t mailstream_low_socket_read(mailstream_low * s,
153 void * buf, size_t count)
154{
155 struct mailstream_socket_data * socket_data;
156
157 socket_data = (struct mailstream_socket_data *) s->data;
158
159 /* timeout */
160 {
161 fd_set fds_read;
162 fd_set fds_excp;
163 struct timeval timeout;
164 int r;
165
166 timeout = mailstream_network_delay;
167
168 FD_ZERO(&fds_read);
169 FD_SET(socket_data->fd, &fds_read);
170 FD_ZERO(&fds_excp);
171 FD_SET(socket_data->fd, &fds_excp);
172 r = select(socket_data->fd + 1, &fds_read, NULL, &fds_excp, &timeout);
173 if (r == 0)
174 return -1;
175 if (FD_ISSET(socket_data->fd, &fds_excp))
176 return -1;
177 if (!FD_ISSET(socket_data->fd, &fds_read))
178 return 0;
179 }
180
181 return read(socket_data->fd, buf, count);
182}
183
184static ssize_t mailstream_low_socket_write(mailstream_low * s,
185 const void * buf, size_t count)
186{
187 struct mailstream_socket_data * socket_data;
188
189 socket_data = (struct mailstream_socket_data *) s->data;
190 /* timeout */
191 {
192 fd_set fds_write;
193 fd_set fds_excp;
194 struct timeval timeout;
195 int r;
196
197 timeout = mailstream_network_delay;
198
199 FD_ZERO(&fds_write);
200 FD_SET(socket_data->fd, &fds_write);
201 FD_ZERO(&fds_excp);
202 FD_SET(socket_data->fd, &fds_excp);
203 r = select(socket_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout);
204 if (r == 0)
205 return -1;
206 if (FD_ISSET(socket_data->fd, &fds_excp))
207 return -1;
208 if (!FD_ISSET(socket_data->fd, &fds_write))
209 return 0;
210 }
211
212 return write(socket_data->fd, buf, count);
213}
214
215
216/* mailstream */
217
218mailstream * mailstream_socket_open(int fd)
219{
220 mailstream_low * low;
221 mailstream * s;
222
223 low = mailstream_low_socket_open(fd);
224 if (low == NULL)
225 goto err;
226
227 s = mailstream_new(low, 8192);
228 if (s == NULL)
229 goto free_low;
230
231 return s;
232
233 free_low:
234 mailstream_low_close(low);
235 err:
236 return NULL;
237}
238
diff --git a/libetpan/src/data-types/mailstream_socket.h b/libetpan/src/data-types/mailstream_socket.h
new file mode 100644
index 0000000..9cf6ada
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_socket.h
@@ -0,0 +1,61 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_SOCKET_H
37
38#define MAILSTREAM_SOCKET_H
39
40#include <libetpan/mailstream.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* socket */
47
48extern mailstream_low_driver * mailstream_socket_driver;
49
50mailstream_low * mailstream_low_socket_open(int fd);
51mailstream * mailstream_socket_open(int fd);
52
53struct mailstream_socket_data {
54 int fd;
55};
56
57#ifdef __cplusplus
58}
59#endif
60
61#endif
diff --git a/libetpan/src/data-types/mailstream_ssl.c b/libetpan/src/data-types/mailstream_ssl.c
new file mode 100644
index 0000000..e57fa22
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_ssl.c
@@ -0,0 +1,320 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 NOTE :
38
39 The user has to call himself SSL_library_init() if he wants to
40 use SSL.
41*/
42
43#include "mailstream_ssl.h"
44#include <unistd.h>
45#include <fcntl.h>
46
47#ifndef CONFIG_H
48#define CONFIG_H
49#include "config.h"
50#endif
51
52/*
53 these 3 headers MUST be included before <sys/select.h>
54 to insure compatibility with Mac OS X (this is true for 10.2)
55*/
56#include <sys/time.h>
57#include <sys/types.h>
58#include <unistd.h>
59#include <sys/select.h>
60
61/* mailstream_low, ssl */
62
63#ifdef USE_SSL
64#include <openssl/ssl.h>
65#ifdef LIBETPAN_REENTRANT
66#include <pthread.h>
67#endif
68#endif
69
70#ifdef USE_SSL
71struct mailstream_ssl_data {
72 int fd;
73 SSL * ssl_conn;
74 SSL_CTX * ssl_ctx;
75};
76#endif
77
78#ifdef USE_SSL
79#ifdef LIBETPAN_REENTRANT
80static pthread_mutex_t ssl_lock = PTHREAD_MUTEX_INITIALIZER;
81#endif
82static int ssl_init_done = 0;
83#endif
84
85#ifdef USE_SSL
86static int mailstream_low_ssl_close(mailstream_low * s);
87static ssize_t mailstream_low_ssl_read(mailstream_low * s,
88 void * buf, size_t count);
89static ssize_t mailstream_low_ssl_write(mailstream_low * s,
90 const void * buf, size_t count);
91static void mailstream_low_ssl_free(mailstream_low * s);
92static int mailstream_low_ssl_get_fd(mailstream_low * s);
93
94static mailstream_low_driver local_mailstream_ssl_driver = {
95 mailstream_read: mailstream_low_ssl_read,
96 mailstream_write: mailstream_low_ssl_write,
97 mailstream_close: mailstream_low_ssl_close,
98 mailstream_free: mailstream_low_ssl_free,
99 mailstream_get_fd: mailstream_low_ssl_get_fd,
100};
101
102mailstream_low_driver * mailstream_ssl_driver = &local_mailstream_ssl_driver;
103#endif
104
105/* file descriptor must be given in (default) blocking-mode */
106
107#ifdef USE_SSL
108static struct mailstream_ssl_data * ssl_data_new(int fd)
109{
110 struct mailstream_ssl_data * ssl_data;
111 SSL * ssl_conn;
112 int r;
113 SSL_CTX * tmp_ctx;
114 int fd_flags;
115 int old_fd_flags;
116
117#ifdef LIBETPAN_REENTRANT
118 pthread_mutex_lock(&ssl_lock);
119#endif
120 if (!ssl_init_done) {
121 SSL_library_init();
122 ssl_init_done = 1;
123 }
124#ifdef LIBETPAN_REENTRANT
125 pthread_mutex_unlock(&ssl_lock);
126#endif
127
128 tmp_ctx = SSL_CTX_new(TLSv1_client_method());
129 if (tmp_ctx == NULL)
130 goto err;
131
132 ssl_conn = (SSL *) SSL_new(tmp_ctx);
133 if (ssl_conn == NULL)
134 goto free_ctx;
135
136 if (SSL_set_fd(ssl_conn, fd) == 0)
137 goto free_ssl_conn;
138
139 SSL_set_read_ahead(ssl_conn, 1);
140
141 r = SSL_connect(ssl_conn);
142 if (r <= 0)
143 goto free_ssl_conn;
144
145 fd_flags = fcntl(fd, F_GETFL, 0);
146 old_fd_flags = fd_flags;
147 fd_flags |= O_NDELAY;
148 r = fcntl(fd, F_SETFL, fd_flags);
149 if (r < 0)
150 goto free_ssl_conn;
151
152 ssl_data = malloc(sizeof(* ssl_data));
153 if (ssl_data == NULL)
154 goto reset_fd_flags;
155
156 ssl_data->fd = fd;
157 ssl_data->ssl_conn = ssl_conn;
158 ssl_data->ssl_ctx = tmp_ctx;
159
160 return ssl_data;
161
162 reset_fd_flags:
163 fcntl(fd, F_SETFL, old_fd_flags);
164 free_ctx:
165 SSL_CTX_free(tmp_ctx);
166 free_ssl_conn:
167 SSL_free(ssl_conn);
168 err:
169 return NULL;
170}
171
172static void ssl_data_free(struct mailstream_ssl_data * ssl_data)
173{
174 free(ssl_data);
175}
176
177static void ssl_data_close(struct mailstream_ssl_data * ssl_data)
178{
179 SSL_free(ssl_data->ssl_conn);
180 ssl_data->ssl_conn = NULL;
181 SSL_CTX_free(ssl_data->ssl_ctx);
182 ssl_data->ssl_ctx = NULL;
183 close(ssl_data->fd);
184 ssl_data->fd = -1;
185}
186#endif
187
188mailstream_low * mailstream_low_ssl_open(int fd)
189{
190#ifdef USE_SSL
191 mailstream_low * s;
192 struct mailstream_ssl_data * ssl_data;
193
194 ssl_data = ssl_data_new(fd);
195 if (ssl_data == NULL)
196 goto err;
197
198 s = mailstream_low_new(ssl_data, mailstream_ssl_driver);
199 if (s == NULL)
200 goto free_ssl_data;
201
202 return s;
203
204 free_ssl_data:
205 ssl_data_free(ssl_data);
206 err:
207 return NULL;
208#else
209 return NULL;
210#endif
211}
212
213#ifdef USE_SSL
214static int mailstream_low_ssl_close(mailstream_low * s)
215{
216 struct mailstream_ssl_data * ssl_data;
217
218 ssl_data = (struct mailstream_ssl_data *) s->data;
219 ssl_data_close(ssl_data);
220
221 return 0;
222}
223
224static void mailstream_low_ssl_free(mailstream_low * s)
225{
226 struct mailstream_ssl_data * ssl_data;
227
228 ssl_data = (struct mailstream_ssl_data *) s->data;
229 ssl_data_free(ssl_data);
230 s->data = NULL;
231
232 free(s);
233}
234
235static int mailstream_low_ssl_get_fd(mailstream_low * s)
236{
237 struct mailstream_ssl_data * ssl_data;
238
239 ssl_data = (struct mailstream_ssl_data *) s->data;
240 return ssl_data->fd;
241}
242
243static ssize_t mailstream_low_ssl_read(mailstream_low * s,
244 void * buf, size_t count)
245{
246 struct mailstream_ssl_data * ssl_data;
247 int r;
248
249 ssl_data = (struct mailstream_ssl_data *) s->data;
250
251 while (1) {
252 int ssl_r;
253 fd_set fds_read;
254 struct timeval timeout;
255
256 r = SSL_read(ssl_data->ssl_conn, buf, count);
257 if (r > 0)
258 return r;
259
260 ssl_r = SSL_get_error(ssl_data->ssl_conn, r);
261 switch (ssl_r) {
262 case SSL_ERROR_NONE:
263 return r;
264
265 case SSL_ERROR_ZERO_RETURN:
266 return r;
267
268 case SSL_ERROR_WANT_READ:
269 timeout = mailstream_network_delay;
270
271 FD_ZERO(&fds_read);
272 FD_SET(ssl_data->fd, &fds_read);
273 r = select(ssl_data->fd + 1, &fds_read, NULL, NULL, &timeout);
274 if (r == 0)
275 return -1;
276 break;
277
278 default:
279 return r;
280 }
281 }
282}
283
284static ssize_t mailstream_low_ssl_write(mailstream_low * s,
285 const void * buf, size_t count)
286{
287 struct mailstream_ssl_data * ssl_data;
288
289 ssl_data = (struct mailstream_ssl_data *) s->data;
290 return SSL_write(ssl_data->ssl_conn, buf, count);
291}
292#endif
293
294/* mailstream */
295
296mailstream * mailstream_ssl_open(int fd)
297{
298#ifdef USE_SSL
299 mailstream_low * low;
300 mailstream * s;
301
302 low = mailstream_low_ssl_open(fd);
303 if (low == NULL)
304 goto err;
305
306 s = mailstream_new(low, 8192);
307 if (s == NULL)
308 goto free_low;
309
310 return s;
311
312 free_low:
313 mailstream_low_close(low);
314 err:
315 return NULL;
316#else
317 return NULL;
318#endif
319}
320
diff --git a/libetpan/src/data-types/mailstream_ssl.h b/libetpan/src/data-types/mailstream_ssl.h
new file mode 100644
index 0000000..bc14d25
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_ssl.h
@@ -0,0 +1,59 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_SSL_H
37
38#define MAILSTREAM_SSL_H
39
40#include <libetpan/mailstream.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/* socket */
47
48#ifdef USE_SSL
49extern mailstream_low_driver * mailstream_ssl_driver;
50#endif
51
52mailstream_low * mailstream_low_ssl_open(int fd);
53mailstream * mailstream_ssl_open(int fd);
54
55#ifdef __cplusplus
56}
57#endif
58
59#endif
diff --git a/libetpan/src/data-types/mailstream_types.h b/libetpan/src/data-types/mailstream_types.h
new file mode 100644
index 0000000..b560ebb
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_types.h
@@ -0,0 +1,87 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTREAM_TYPES_H
37
38#define MAILSTREAM_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#define LIBETPAN_MAILSTREAM_DEBUG
45
46struct _mailstream;
47
48typedef struct _mailstream mailstream;
49
50struct _mailstream_low;
51
52typedef struct _mailstream_low mailstream_low;
53
54struct _mailstream {
55 size_t buffer_max_size;
56
57 char * write_buffer;
58 size_t write_buffer_len;
59
60 char * read_buffer;
61 size_t read_buffer_len;
62
63 mailstream_low * low;
64};
65
66struct mailstream_low_driver {
67 ssize_t (* mailstream_read)(mailstream_low *, void *, size_t);
68 ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t);
69 int (* mailstream_close)(mailstream_low *);
70 int (* mailstream_get_fd)(mailstream_low *);
71 void (* mailstream_free)(mailstream_low *);
72};
73
74typedef struct mailstream_low_driver mailstream_low_driver;
75
76struct _mailstream_low {
77 void * data;
78 mailstream_low_driver * driver;
79};
80
81typedef void progress_function(size_t current, size_t maximum);
82
83#ifdef __cplusplus
84}
85#endif
86
87#endif
diff --git a/libetpan/src/data-types/mapping.c b/libetpan/src/data-types/mapping.c
new file mode 100644
index 0000000..5f2c4a4
--- a/dev/null
+++ b/libetpan/src/data-types/mapping.c
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mapping.h"
37
38#include <unistd.h>
39#include <sys/mman.h>
40
41int get_mapping(size_t length, int prot, int flags,
42 int fd, off_t offset,
43 void ** presult, void ** pmapping, size_t * pmapping_size)
44{
45 void * mapping;
46 size_t mapping_size;
47 void * result;
48 size_t page_size;
49 off_t delta;
50
51 page_size = getpagesize();
52 delta = offset % page_size;
53
54 mapping = mmap(NULL, length + offset, prot, flags, fd, offset - delta);
55 if (mapping == MAP_FAILED)
56 return -1;
57
58 result = ((char *) mapping) + delta;
59
60 mapping_size = length + offset;
61
62 * pmapping = mapping;
63 * pmapping_size = mapping_size;
64 * presult = result;
65
66 return 0;
67}
diff --git a/libetpan/src/data-types/mapping.h b/libetpan/src/data-types/mapping.h
new file mode 100644
index 0000000..d33f035
--- a/dev/null
+++ b/libetpan/src/data-types/mapping.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAPPING_H
37
38#define MAPPING_H
39
40#include <sys/types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46int get_mapping(size_t length, int prot, int flags,
47 int fd, off_t offset,
48 void ** presult, void ** pmapping, size_t * pmapping_size);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/data-types/md5.c b/libetpan/src/data-types/md5.c
new file mode 100644
index 0000000..3c46b5e
--- a/dev/null
+++ b/libetpan/src/data-types/md5.c
@@ -0,0 +1,570 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
37*/
38
39/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
40rights reserved.
41
42License to copy and use this software is granted provided that it
43is identified as the "RSA Data Security, Inc. MD5 Message-Digest
44Algorithm" in all material mentioning or referencing this software
45or this function.
46
47License is also granted to make and use derivative works provided
48that such works are identified as "derived from the RSA Data
49Security, Inc. MD5 Message-Digest Algorithm" in all material
50mentioning or referencing the derived work.
51
52RSA Data Security, Inc. makes no representations concerning either
53the merchantability of this software or the suitability of this
54software for any particular purpose. It is provided "as is"
55without express or implied warranty of any kind.
56
57These notices must be retained in any copies of any part of this
58documentation and/or software.
59*/
60
61/* do i need all of this just for htonl()? damn. */
62#include <sys/types.h>
63#include <sys/param.h>
64#include <sys/socket.h>
65#include <netinet/in.h>
66
67#include "md5global.h"
68#include "md5.h"
69#include "hmac-md5.h"
70
71/* Constants for MD5Transform routine.
72*/
73
74#define S11 7
75#define S12 12
76#define S13 17
77#define S14 22
78#define S21 5
79#define S22 9
80#define S23 14
81#define S24 20
82#define S31 4
83#define S32 11
84#define S33 16
85#define S34 23
86#define S41 6
87#define S42 10
88#define S43 15
89#define S44 21
90
91static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
92static void Encode PROTO_LIST
93 ((unsigned char *, UINT4 *, unsigned int));
94static void Decode PROTO_LIST
95 ((UINT4 *, unsigned char *, unsigned int));
96static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
97static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
98
99static unsigned char PADDING[64] = {
100 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,
101 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
102};
103
104/* F, G, H and I are basic MD5 functions.
105
106 */
107#ifdef I
108/* This might be defined via NANA */
109#undef I
110#endif
111
112#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
113#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
114#define H(x, y, z) ((x) ^ (y) ^ (z))
115#define I(x, y, z) ((y) ^ ((x) | (~z)))
116
117/* ROTATE_LEFT rotates x left n bits.
118
119 */
120
121#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
122
123/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
124Rotation is separate from addition to prevent recomputation.
125*/
126
127#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
128#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
129#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
130#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
131
132/* MD5 initialization. Begins an MD5 operation, writing a new context.
133*/
134
135void MD5Init (context)
136MD5_CTX *context; /* context */
137{
138 context->count[0] = context->count[1] = 0;
139
140 /* Load magic initialization constants.
141
142*/
143 context->state[0] = 0x67452301;
144 context->state[1] = 0xefcdab89;
145 context->state[2] = 0x98badcfe;
146 context->state[3] = 0x10325476;
147}
148
149/* MD5 block update operation. Continues an MD5 message-digest
150 operation, processing another message block, and updating the context.
151*/
152
153void MD5Update (context, input, inputLen)
154MD5_CTX *context; /* context */
155unsigned char *input; /* input block */
156unsigned int inputLen; /* length of input block */
157{
158 unsigned int i, index, partLen;
159
160 /* Compute number of bytes mod 64 */
161 index = (unsigned int)((context->count[0] >> 3) & 0x3F);
162
163 /* Update number of bits */
164 if ((context->count[0] += ((UINT4)inputLen << 3))
165 < ((UINT4)inputLen << 3))
166 context->count[1]++;
167 context->count[1] += ((UINT4)inputLen >> 29);
168
169 partLen = 64 - index;
170
171 /* Transform as many times as possible.
172
173*/
174 if (inputLen >= partLen) {
175 MD5_memcpy
176 ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform
177 (context->state, context->buffer);
178
179 for (i = partLen; i + 63 < inputLen; i += 64)
180 MD5Transform (context->state, &input[i]);
181
182 index = 0;
183 }
184 else
185 i = 0;
186
187 /* Buffer remaining input */
188 MD5_memcpy
189 ((POINTER)&context->buffer[index], (POINTER)&input[i],
190 inputLen-i);
191
192}
193
194/* MD5 finalization. Ends an MD5 message-digest operation, writing the
195 the message digest and zeroizing the context.
196
197 */
198
199void MD5Final (digest, context)
200unsigned char digest[16]; /* message digest */
201MD5_CTX *context; /* context */
202{
203 unsigned char bits[8];
204 unsigned int index, padLen;
205
206 /* Save number of bits */
207 Encode (bits, context->count, 8);
208
209 /* Pad out to 56 mod 64.
210
211*/
212 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
213 padLen = (index < 56) ? (56 - index) : (120 - index);
214 MD5Update (context, PADDING, padLen);
215
216 /* Append length (before padding) */
217 MD5Update (context, bits, 8);
218
219 /* Store state in digest */
220 Encode (digest, context->state, 16);
221
222 /* Zeroize sensitive information.
223
224*/
225 MD5_memset ((POINTER)context, 0, sizeof (*context));
226}
227
228/* MD5 basic transformation. Transforms state based on block.
229
230 */
231
232static void MD5Transform (state, block)
233UINT4 state[4];
234unsigned char block[64];
235{
236 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
237
238 Decode (x, block, 64);
239
240 /* Round 1 */
241 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
242 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
243 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
244 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
245 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
246 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
247 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
248 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
249 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
250 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
251 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
252 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
253 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
254 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
255 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
256 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
257
258 /* Round 2 */
259 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
260 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
261 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
262 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
263 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
264 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
265 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
266 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
267 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
268 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
269 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
270 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
271 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
272 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
273 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
274 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
275
276 /* Round 3 */
277 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
278 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
279 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
280 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
281 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
282 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
283 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
284 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
285 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
286 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
287 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
288 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
289 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
290 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
291 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
292 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
293
294 /* Round 4 */
295 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
296 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
297 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
298 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
299 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
300 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
301 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
302 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
303 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
304 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
305 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
306 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
307 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
308 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
309 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
310 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
311
312 state[0] += a;
313 state[1] += b;
314 state[2] += c;
315 state[3] += d;
316
317 /* Zeroize sensitive information.
318 */
319 MD5_memset ((POINTER)x, 0, sizeof (x));
320}
321
322/* Encodes input (UINT4) into output (unsigned char). Assumes len is
323 a multiple of 4.
324
325 */
326
327static void Encode (output, input, len)
328unsigned char *output;
329UINT4 *input;
330unsigned int len;
331{
332 unsigned int i, j;
333
334 for (i = 0, j = 0; j < len; i++, j += 4) {
335 output[j] = (unsigned char)(input[i] & 0xff);
336 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
337 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
338 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
339 }
340}
341
342/* Decodes input (unsigned char) into output (UINT4). Assumes len is
343 a multiple of 4.
344
345 */
346
347static void Decode (output, input, len)
348UINT4 *output;
349unsigned char *input;
350unsigned int len;
351{
352 unsigned int i, j;
353
354 for (i = 0, j = 0; j < len; i++, j += 4)
355 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
356 | (((UINT4)input[j+3]) << 24);
357}
358
359/* Note: Replace "for loop" with standard memcpy if possible.
360
361 */
362
363static void MD5_memcpy (output, input, len)
364POINTER output;
365POINTER input;
366unsigned int len;
367{
368 unsigned int i;
369
370 for (i = 0; i < len; i++)
371 output[i] = input[i];
372}
373
374/* Note: Replace "for loop" with standard memset if possible.
375*/
376
377static void MD5_memset (output, value, len)
378POINTER output;
379int value;
380unsigned int len;
381{
382 unsigned int i;
383
384 for (i = 0; i < len; i++)
385 ((char *)output)[i] = (char)value;
386}
387
388void hmac_md5_init(HMAC_MD5_CTX *hmac,
389 const unsigned char *key,
390 int key_len)
391{
392 unsigned char k_ipad[65]; /* inner padding -
393 * key XORd with ipad
394 */
395 unsigned char k_opad[65]; /* outer padding -
396 * key XORd with opad
397 */
398 unsigned char tk[16];
399 int i;
400 /* if key is longer than 64 bytes reset it to key=MD5(key) */
401 if (key_len > 64) {
402
403 MD5_CTX tctx;
404
405 MD5Init(&tctx);
406 MD5Update(&tctx, key, key_len);
407 MD5Final(tk, &tctx);
408
409 key = tk;
410 key_len = 16;
411 }
412
413 /*
414 * the HMAC_MD5 transform looks like:
415 *
416 * MD5(K XOR opad, MD5(K XOR ipad, text))
417 *
418 * where K is an n byte key
419 * ipad is the byte 0x36 repeated 64 times
420 * opad is the byte 0x5c repeated 64 times
421 * and text is the data being protected
422 */
423
424 /* start out by storing key in pads */
425 MD5_memset(k_ipad, '\0', sizeof k_ipad);
426 MD5_memset(k_opad, '\0', sizeof k_opad);
427 MD5_memcpy( k_ipad, key, key_len);
428 MD5_memcpy( k_opad, key, key_len);
429
430 /* XOR key with ipad and opad values */
431 for (i=0; i<64; i++) {
432 k_ipad[i] ^= 0x36;
433 k_opad[i] ^= 0x5c;
434 }
435
436 MD5Init(&hmac->ictx); /* init inner context */
437 MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */
438
439 MD5Init(&hmac->octx); /* init outer context */
440 MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */
441
442 /* scrub the pads and key context (if used) */
443 MD5_memset(&k_ipad, 0, sizeof(k_ipad));
444 MD5_memset(&k_opad, 0, sizeof(k_opad));
445 MD5_memset(&tk, 0, sizeof(tk));
446
447 /* and we're done. */
448}
449
450/* The precalc and import routines here rely on the fact that we pad
451 * the key out to 64 bytes and use that to initialize the md5
452 * contexts, and that updating an md5 context with 64 bytes of data
453 * leaves nothing left over; all of the interesting state is contained
454 * in the state field, and none of it is left over in the count and
455 * buffer fields. So all we have to do is save the state field; we
456 * can zero the others when we reload it. Which is why the decision
457 * was made to pad the key out to 64 bytes in the first place. */
458void hmac_md5_precalc(HMAC_MD5_STATE *state,
459 const unsigned char *key,
460 int key_len)
461{
462 HMAC_MD5_CTX hmac;
463 unsigned lupe;
464
465 hmac_md5_init(&hmac, key, key_len);
466 for (lupe = 0; lupe < 4; lupe++) {
467 state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
468 state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
469 }
470 MD5_memset(&hmac, 0, sizeof(hmac));
471}
472
473
474void hmac_md5_import(HMAC_MD5_CTX *hmac,
475 HMAC_MD5_STATE *state)
476{
477 unsigned lupe;
478 MD5_memset(hmac, 0, sizeof(HMAC_MD5_CTX));
479 for (lupe = 0; lupe < 4; lupe++) {
480 hmac->ictx.state[lupe] = ntohl(state->istate[lupe]);
481 hmac->octx.state[lupe] = ntohl(state->ostate[lupe]);
482 }
483 /* Init the counts to account for our having applied
484 * 64 bytes of key; this works out to 0x200 (64 << 3; see
485 * MD5Update above...) */
486 hmac->ictx.count[0] = hmac->octx.count[0] = 0x200;
487}
488
489void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
490 HMAC_MD5_CTX *hmac)
491{
492 MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */
493 MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */
494 MD5Final(digest, &hmac->octx); /* Finalize outer md5 */
495}
496
497
498void hmac_md5(text, text_len, key, key_len, digest)
499const unsigned char* text; /* pointer to data stream */
500int text_len; /* length of data stream */
501const unsigned char* key; /* pointer to authentication key */
502int key_len; /* length of authentication key */
503unsigned char *digest; /* caller digest to be filled in */
504{
505 MD5_CTX context;
506
507 unsigned char k_ipad[65]; /* inner padding -
508 * key XORd with ipad
509 */
510 unsigned char k_opad[65]; /* outer padding -
511 * key XORd with opad
512 */
513 unsigned char tk[16];
514 int i;
515 /* if key is longer than 64 bytes reset it to key=MD5(key) */
516 if (key_len > 64) {
517
518 MD5_CTX tctx;
519
520 MD5Init(&tctx);
521 MD5Update(&tctx, key, key_len);
522 MD5Final(tk, &tctx);
523
524 key = tk;
525 key_len = 16;
526 }
527
528 /*
529 * the HMAC_MD5 transform looks like:
530 *
531 * MD5(K XOR opad, MD5(K XOR ipad, text))
532 *
533 * where K is an n byte key
534 * ipad is the byte 0x36 repeated 64 times
535 * opad is the byte 0x5c repeated 64 times
536 * and text is the data being protected
537 */
538
539 /* start out by storing key in pads */
540 MD5_memset(k_ipad, '\0', sizeof k_ipad);
541 MD5_memset(k_opad, '\0', sizeof k_opad);
542 MD5_memcpy( k_ipad, key, key_len);
543 MD5_memcpy( k_opad, key, key_len);
544
545 /* XOR key with ipad and opad values */
546 for (i=0; i<64; i++) {
547 k_ipad[i] ^= 0x36;
548 k_opad[i] ^= 0x5c;
549 }
550 /*
551 * perform inner MD5
552 */
553
554 MD5Init(&context); /* init context for 1st
555 * pass */
556 MD5Update(&context, k_ipad, 64); /* start with inner pad */
557 MD5Update(&context, text, text_len); /* then text of datagram */
558 MD5Final(digest, &context); /* finish up 1st pass */
559
560 /*
561 * perform outer MD5
562 */
563 MD5Init(&context); /* init context for 2nd
564 * pass */
565 MD5Update(&context, k_opad, 64); /* start with outer pad */
566 MD5Update(&context, digest, 16); /* then results of 1st
567 * hash */
568 MD5Final(digest, &context); /* finish up 2nd pass */
569
570}
diff --git a/libetpan/src/data-types/md5.h b/libetpan/src/data-types/md5.h
new file mode 100644
index 0000000..971652e
--- a/dev/null
+++ b/libetpan/src/data-types/md5.h
@@ -0,0 +1,88 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/* MD5.H - header file for MD5C.C
37 */
38
39/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
40rights reserved.
41
42License to copy and use this software is granted provided that it
43is identified as the "RSA Data Security, Inc. MD5 Message-Digest
44Algorithm" in all material mentioning or referencing this software
45or this function.
46
47License is also granted to make and use derivative works provided
48that such works are identified as "derived from the RSA Data
49Security, Inc. MD5 Message-Digest Algorithm" in all material
50mentioning or referencing the derived work.
51
52RSA Data Security, Inc. makes no representations concerning either
53the merchantability of this software or the suitability of this
54software for any particular purpose. It is provided "as is"
55without express or implied warranty of any kind.
56These notices must be retained in any copies of any part of this
57documentation and/or software.
58 */
59
60#include "md5global.h"
61
62#ifndef MD5_H
63
64#define MD5_H
65
66#ifdef __cplusplus
67extern "C" {
68#endif
69
70/* MD5 context. */
71typedef struct {
72 UINT4 state[4]; /* state (ABCD) */
73 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
74 unsigned char buffer[64]; /* input buffer */
75} MD5_CTX;
76
77void MD5Init PROTO_LIST ((MD5_CTX *));
78void MD5Update PROTO_LIST
79 ((MD5_CTX *, unsigned char *, unsigned int));
80void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
81
82void hmac_md5 PROTO_LIST ((unsigned char *, int, unsigned char *, int, caddr_t));
83
84#ifdef __cplusplus
85}
86#endif
87
88#endif
diff --git a/libetpan/src/data-types/md5global.h b/libetpan/src/data-types/md5global.h
new file mode 100644
index 0000000..093d0c9
--- a/dev/null
+++ b/libetpan/src/data-types/md5global.h
@@ -0,0 +1,79 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/* GLOBAL.H - RSAREF types and constants
37 */
38
39#ifndef MD5GLOBAL_H
40
41#define MD5GLOBAL_H
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* PROTOTYPES should be set to one if and only if the compiler supports
48 function argument prototyping.
49The following makes PROTOTYPES default to 0 if it has not already
50 been defined with C compiler flags.
51 */
52#ifndef PROTOTYPES
53#define PROTOTYPES 0
54#endif
55
56/* POINTER defines a generic pointer type */
57typedef unsigned char *POINTER;
58
59/* UINT2 defines a two byte word */
60typedef unsigned short int UINT2;
61
62/* UINT4 defines a four byte word */
63typedef unsigned long int UINT4;
64
65/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
66If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
67 returns an empty list.
68 */
69#if PROTOTYPES
70#define PROTO_LIST(list) list
71#else
72#define PROTO_LIST(list) ()
73#endif
74
75#ifdef __cplusplus
76}
77#endif
78
79#endif
diff --git a/libetpan/src/data-types/mmapstring.c b/libetpan/src/data-types/mmapstring.c
new file mode 100644
index 0000000..37c681c
--- a/dev/null
+++ b/libetpan/src/data-types/mmapstring.c
@@ -0,0 +1,551 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mmapstring.h"
37
38#include "chash.h"
39
40#ifndef CONFIG_H
41#define CONFIG_H
42#include "config.h"
43#endif
44
45#include <stdlib.h>
46#include <unistd.h>
47#include <sys/mman.h>
48#include <string.h>
49#ifdef LIBETPAN_REENTRANT
50#include <pthread.h>
51#endif
52
53#include "libetpan-config.h"
54
55#define MMAPSTRING_MAX(a, b) ((a) > (b) ? (a) : (b))
56#define MMAPSTRING_MIN(a, b) ((a) < (b) ? (a) : (b))
57
58#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024)
59
60#define DEFAULT_TMP_PATH "/tmp"
61
62static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH;
63
64static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL;
65
66/* MMAPString references */
67
68#ifdef LIBETPAN_REENTRANT
69static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER;
70#endif
71static chash * mmapstring_hashtable = NULL;
72
73static void mmapstring_hashtable_init()
74{
75 mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
76}
77
78void mmap_string_set_tmpdir(char * directory)
79{
80 strncpy(tmpdir, directory, PATH_MAX);
81 tmpdir[PATH_MAX - 1] = 0;
82}
83
84
85int mmap_string_ref(MMAPString * string)
86{
87 chash * ht;
88 int r;
89 chashdatum key;
90 chashdatum data;
91
92#ifdef LIBETPAN_REENTRANT
93 pthread_mutex_lock(&mmapstring_lock);
94#endif
95 if (mmapstring_hashtable == NULL) {
96 mmapstring_hashtable_init();
97 }
98 ht = mmapstring_hashtable;
99
100 if (ht == NULL) {
101#ifdef LIBETPAN_REENTRANT
102 pthread_mutex_unlock(&mmapstring_lock);
103#endif
104 return -1;
105 }
106
107 key.data = &string->str;
108 key.len = sizeof(string->str);
109 data.data = string;
110 data.len = 0;
111
112 r = chash_set(mmapstring_hashtable, &key, &data, NULL);
113#ifdef LIBETPAN_REENTRANT
114 pthread_mutex_unlock(&mmapstring_lock);
115#endif
116
117 if (r < 0)
118 return r;
119
120 return 0;
121}
122
123int mmap_string_unref(char * str)
124{
125 MMAPString * string;
126 chash * ht;
127 chashdatum key;
128 chashdatum data;
129 int r;
130
131#ifdef LIBETPAN_REENTRANT
132 pthread_mutex_lock(&mmapstring_lock);
133#endif
134 ht = mmapstring_hashtable;
135
136 if (ht == NULL) {
137#ifdef LIBETPAN_REENTRANT
138 pthread_mutex_unlock(&mmapstring_lock);
139#endif
140 return -1;
141 }
142
143 key.data = &str;
144 key.len = sizeof(str);
145
146 r = chash_get(ht, &key, &data);
147 if (r < 0)
148 string = NULL;
149 else
150 string = data.data;
151
152 if (string != NULL) {
153 chash_delete(ht, &key, NULL);
154 if (chash_count(ht) == 0) {
155 chash_free(ht);
156 mmapstring_hashtable = NULL;
157 }
158 }
159
160#ifdef LIBETPAN_REENTRANT
161 pthread_mutex_unlock(&mmapstring_lock);
162#endif
163
164 if (string != NULL) {
165 mmap_string_free(string);
166 return 0;
167 }
168 else
169 return -1;
170}
171
172
173
174/* MMAPString */
175
176#define MY_MAXSIZE ((size_t) -1)
177
178static inline size_t
179nearest_power (size_t base, size_t num)
180{
181 if (num > MY_MAXSIZE / 2) {
182 return MY_MAXSIZE;
183 }
184 else {
185 size_t n = base;
186
187 while (n < num)
188 n <<= 1;
189
190 return n;
191 }
192}
193
194void mmap_string_set_ceil(size_t ceil)
195{
196 mmap_string_ceil = ceil;
197}
198
199/* Strings.
200 */
201
202static MMAPString * mmap_string_realloc_file(MMAPString * string)
203{
204 char * data;
205
206 if (string->fd == -1) {
207 char tmpfilename[PATH_MAX];
208 int fd;
209
210 * tmpfilename = 0;
211 strcat(tmpfilename, tmpdir);
212 strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX");
213
214 fd = mkstemp(tmpfilename);
215 if (fd == -1)
216 return NULL;
217
218 if (unlink(tmpfilename) == -1) {
219 close(fd);
220 return NULL;
221 }
222
223 if (ftruncate(fd, string->allocated_len) == -1) {
224 close(fd);
225 return NULL;
226 }
227
228 data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
229 MAP_SHARED, fd, 0);
230
231 if (data == MAP_FAILED) {
232 close(fd);
233 return NULL;
234 }
235
236 if (string->str != NULL)
237 memcpy(data, string->str, string->len + 1);
238
239 string->fd = fd;
240 string->mmapped_size = string->allocated_len;
241 free(string->str);
242 string->str = data;
243 }
244 else {
245 if (munmap(string->str, string->mmapped_size) == -1)
246 return NULL;
247
248 if (ftruncate(string->fd, string->allocated_len) == -1)
249 return NULL;
250
251 data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
252 MAP_SHARED, string->fd, 0);
253
254 if (data == MAP_FAILED)
255 return NULL;
256
257 string->mmapped_size = string->allocated_len;
258 string->str = data;
259 }
260
261 return string;
262}
263
264static MMAPString * mmap_string_realloc_memory(MMAPString * string)
265{
266 char * tmp;
267
268 tmp = realloc (string->str, string->allocated_len);
269
270 if (tmp == NULL)
271 string = NULL;
272 else
273 string->str = tmp;
274
275 return string;
276}
277
278static MMAPString *
279mmap_string_maybe_expand (MMAPString* string,
280 size_t len)
281{
282 if (string->len + len >= string->allocated_len)
283 {
284 size_t old_size;
285 MMAPString * newstring;
286
287 old_size = string->allocated_len;
288
289 string->allocated_len = nearest_power (1, string->len + len + 1);
290
291#ifndef MMAP_UNAVAILABLE
292 if (string->allocated_len > mmap_string_ceil)
293 newstring = mmap_string_realloc_file(string);
294 else {
295#endif
296 newstring = mmap_string_realloc_memory(string);
297#ifndef MMAP_UNAVAILABLE
298 if (newstring == NULL)
299 newstring = mmap_string_realloc_file(string);
300 }
301#endif
302
303 if (newstring == NULL)
304 string->allocated_len = old_size;
305
306 return newstring;
307 }
308
309 return string;
310}
311
312MMAPString*
313mmap_string_sized_new (size_t dfl_size)
314{
315 MMAPString *string;
316
317 string = malloc(sizeof(* string));
318 if (string == NULL)
319 return NULL;
320
321 string->allocated_len = 0;
322 string->len = 0;
323 string->str = NULL;
324 string->fd = -1;
325 string->mmapped_size = 0;
326
327 if (mmap_string_maybe_expand (string, MMAPSTRING_MAX (dfl_size, 2)) == NULL)
328 return NULL;
329
330 string->str[0] = 0;
331
332 return string;
333}
334
335MMAPString*
336mmap_string_new (const char *init)
337{
338 MMAPString *string;
339
340 string = mmap_string_sized_new (init ? strlen (init) + 2 : 2);
341 if (string == NULL)
342 return NULL;
343
344 if (init)
345 mmap_string_append (string, init);
346
347 return string;
348}
349
350MMAPString*
351mmap_string_new_len (const char *init,
352 size_t len)
353{
354 MMAPString *string;
355
356 if (len <= 0)
357 return mmap_string_new ("");
358 else
359 {
360 string = mmap_string_sized_new (len);
361 if (string == NULL)
362 return string;
363
364 if (init)
365 mmap_string_append_len (string, init, len);
366
367 return string;
368 }
369}
370
371void
372mmap_string_free (MMAPString *string)
373{
374 if (string == NULL)
375 return;
376
377 if (string->fd != -1) {
378 munmap(string->str, string->mmapped_size);
379 close(string->fd);
380 }
381 else {
382 free (string->str);
383 }
384 free(string);
385}
386
387MMAPString*
388mmap_string_assign (MMAPString *string,
389 const char *rval)
390{
391 mmap_string_truncate (string, 0);
392 if (mmap_string_append (string, rval) == NULL)
393 return NULL;
394
395 return string;
396}
397
398MMAPString*
399mmap_string_truncate (MMAPString *string,
400 size_t len)
401{
402 string->len = MMAPSTRING_MIN (len, string->len);
403 string->str[string->len] = 0;
404
405 return string;
406}
407
408/**
409 * mmap_string_set_size:
410 * @string: a #MMAPString
411 * @len: the new length
412 *
413 * Sets the length of a #MMAPString. If the length is less than
414 * the current length, the string will be truncated. If the
415 * length is greater than the current length, the contents
416 * of the newly added area are undefined. (However, as
417 * always, string->str[string->len] will be a nul byte.)
418 *
419 * Return value: @string
420 **/
421MMAPString*
422mmap_string_set_size (MMAPString *string,
423 size_t len)
424{
425 if (len >= string->allocated_len)
426 if (mmap_string_maybe_expand (string, len - string->len) == NULL)
427 return NULL;
428
429 string->len = len;
430 string->str[len] = 0;
431
432 return string;
433}
434
435/*
436static int in_mapped_zone(MMAPString * string, char * val)
437{
438 return (val >= string->str) && (val < string->str + string->mmapped_size);
439}
440*/
441
442MMAPString*
443mmap_string_insert_len (MMAPString *string,
444 size_t pos,
445 const char *val,
446 size_t len)
447{
448 if (mmap_string_maybe_expand (string, len) == NULL)
449 return NULL;
450
451 if (pos < string->len)
452 memmove (string->str + pos + len, string->str + pos, string->len - pos);
453
454 /* insert the new string */
455 memmove (string->str + pos, val, len);
456
457 string->len += len;
458
459 string->str[string->len] = 0;
460
461 return string;
462}
463
464MMAPString*
465mmap_string_append (MMAPString *string,
466 const char *val)
467{
468 return mmap_string_insert_len (string, string->len, val, strlen(val));
469}
470
471MMAPString*
472 mmap_string_append_len (MMAPString *string,
473 const char *val,
474 size_t len)
475{
476 return mmap_string_insert_len (string, string->len, val, len);
477}
478
479MMAPString*
480mmap_string_append_c (MMAPString *string,
481 char c)
482{
483 return mmap_string_insert_c (string, string->len, c);
484}
485
486MMAPString*
487mmap_string_prepend (MMAPString *string,
488 const char *val)
489{
490 return mmap_string_insert_len (string, 0, val, strlen(val));
491}
492
493MMAPString*
494 mmap_string_prepend_len (MMAPString *string,
495 const char *val,
496 size_t len)
497{
498 return mmap_string_insert_len (string, 0, val, len);
499}
500
501MMAPString*
502mmap_string_prepend_c (MMAPString *string,
503 char c)
504{
505 return mmap_string_insert_c (string, 0, c);
506}
507
508MMAPString*
509mmap_string_insert (MMAPString *string,
510 size_t pos,
511 const char *val)
512{
513 return mmap_string_insert_len (string, pos, val, strlen(val));
514}
515
516MMAPString*
517mmap_string_insert_c (MMAPString *string,
518 size_t pos,
519 char c)
520{
521 if (mmap_string_maybe_expand (string, 1) == NULL)
522 return NULL;
523
524 /* If not just an append, move the old stuff */
525 if (pos < string->len)
526 memmove (string->str + pos + 1, string->str + pos, string->len - pos);
527
528 string->str[pos] = c;
529
530 string->len += 1;
531
532 string->str[string->len] = 0;
533
534 return string;
535}
536
537MMAPString*
538mmap_string_erase (MMAPString *string,
539 size_t pos,
540 size_t len)
541{
542 if ((pos + len) < string->len)
543 memmove (string->str + pos, string->str + pos + len,
544 string->len - (pos + len));
545
546 string->len -= len;
547
548 string->str[string->len] = 0;
549
550 return string;
551}
diff --git a/libetpan/src/data-types/mmapstring.h b/libetpan/src/data-types/mmapstring.h
new file mode 100644
index 0000000..573e354
--- a/dev/null
+++ b/libetpan/src/data-types/mmapstring.h
@@ -0,0 +1,136 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef __MMAP_STRING_H__
37
38#define __MMAP_STRING_H__
39
40#include <sys/types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47#define TMPDIR "/tmp"
48*/
49
50typedef struct _MMAPString MMAPString;
51
52struct _MMAPString
53{
54 char * str;
55 size_t len;
56 size_t allocated_len;
57 int fd;
58 size_t mmapped_size;
59 /*
60 char * old_non_mmapped_str;
61 */
62};
63
64/* configure location of mmaped files */
65
66void mmap_string_set_tmpdir(char * directory);
67
68/* Strings
69 */
70
71MMAPString * mmap_string_new (const char * init);
72
73MMAPString * mmap_string_new_len (const char * init,
74 size_t len);
75
76MMAPString * mmap_string_sized_new (size_t dfl_size);
77
78void mmap_string_free (MMAPString * string);
79
80MMAPString * mmap_string_assign (MMAPString * string,
81 const char * rval);
82
83MMAPString * mmap_string_truncate (MMAPString *string,
84 size_t len);
85
86MMAPString * mmap_string_set_size (MMAPString * string,
87 size_t len);
88
89MMAPString * mmap_string_insert_len (MMAPString * string,
90 size_t pos,
91 const char * val,
92 size_t len);
93
94MMAPString * mmap_string_append (MMAPString * string,
95 const char * val);
96
97MMAPString * mmap_string_append_len (MMAPString * string,
98 const char * val,
99 size_t len);
100
101MMAPString * mmap_string_append_c (MMAPString * string,
102 char c);
103
104MMAPString * mmap_string_prepend (MMAPString * string,
105 const char * val);
106
107MMAPString * mmap_string_prepend_c (MMAPString * string,
108 char c);
109
110MMAPString * mmap_string_prepend_len (MMAPString * string,
111 const char * val,
112 size_t len);
113
114MMAPString * mmap_string_insert (MMAPString * string,
115 size_t pos,
116 const char * val);
117
118MMAPString * mmap_string_insert_c (MMAPString *string,
119 size_t pos,
120 char c);
121
122MMAPString * mmap_string_erase(MMAPString * string,
123 size_t pos,
124 size_t len);
125
126void mmap_string_set_ceil(size_t ceil);
127
128int mmap_string_ref(MMAPString * string);
129int mmap_string_unref(char * str);
130
131#ifdef __cplusplus
132}
133#endif
134
135
136#endif /* __MMAP_STRING_H__ */
diff --git a/libetpan/src/driver/TODO b/libetpan/src/driver/TODO
new file mode 100644
index 0000000..4ba2c46
--- a/dev/null
+++ b/libetpan/src/driver/TODO
@@ -0,0 +1,9 @@
1- get_message_list() will disconnect and reconnect POP3 box
2- add UID to non-cached drivers, help clients to recognize messages
3- move IMAP UID cache to non-cached driver
4- fix message size (put it in cache)
5- XXX : fetch body in nntp do not use generic_fetch_body
6- add flags prototype to add or remove flags
7- cache bodystructures
8- search is not implemented
9- list of folder new implementation
diff --git a/libetpan/src/driver/implementation/data-message/data_message_driver.c b/libetpan/src/driver/implementation/data-message/data_message_driver.c
new file mode 100644
index 0000000..fbdffcd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/data-message/data_message_driver.c
@@ -0,0 +1,119 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "data_message_driver.h"
37
38#include "mailmessage.h"
39#include "mailmessage_tools.h"
40
41#include <unistd.h>
42#include <sys/mman.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <string.h>
47#include <stdlib.h>
48
49static int fetch_size(mailmessage * msg, size_t * result)
50{
51 struct generic_message_t * msg_data;
52
53 msg_data = msg->msg_data;
54 * result = msg_data->msg_length;
55
56 return MAIL_NO_ERROR;
57}
58
59
60static mailmessage_driver local_data_message_driver = {
61 .msg_name = "data",
62
63 .msg_initialize = mailmessage_generic_initialize,
64 .msg_uninitialize = mailmessage_generic_uninitialize,
65
66 .msg_flush = mailmessage_generic_flush,
67 .msg_check = NULL,
68
69 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
70
71 .msg_fetch = mailmessage_generic_fetch,
72 .msg_fetch_header = mailmessage_generic_fetch_header,
73 .msg_fetch_body = mailmessage_generic_fetch_body,
74 .msg_fetch_size = fetch_size,
75 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
76 .msg_fetch_section = mailmessage_generic_fetch_section,
77 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
78 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
79 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
80 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
81
82 .msg_get_flags = NULL,
83};
84
85mailmessage_driver * data_message_driver = &local_data_message_driver;
86
87
88
89mailmessage * data_message_init(char * data, size_t len)
90{
91 struct generic_message_t * msg_data;
92 mailmessage * msg;
93 int r;
94
95 msg = mailmessage_new();
96 if (msg == NULL)
97 goto err;
98
99 r = mailmessage_init(msg, NULL, data_message_driver, 0, len);
100 if (r < 0)
101 goto free;
102
103 msg_data = msg->msg_data;
104 msg_data->msg_fetched = 1;
105 msg_data->msg_message = data;
106 msg_data->msg_length = len;
107
108 return msg;
109
110 free:
111 mailmessage_free(msg);
112 err:
113 return NULL;
114}
115
116void data_message_detach_mime(mailmessage * msg)
117{
118 msg->msg_mime = NULL;
119}
diff --git a/libetpan/src/driver/implementation/data-message/data_message_driver.h b/libetpan/src/driver/implementation/data-message/data_message_driver.h
new file mode 100644
index 0000000..b6569c2
--- a/dev/null
+++ b/libetpan/src/driver/implementation/data-message/data_message_driver.h
@@ -0,0 +1,50 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DATA_MESSAGE_DRIVER_H
37
38#define DATA_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_DATA_MESSAGE
43
44extern mailmessage_driver * data_message_driver;
45
46mailmessage * data_message_init(char * data, size_t len);
47
48void data_message_detach_mime(mailmessage * msg);
49
50#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver.c b/libetpan/src/driver/implementation/db/dbdriver.c
new file mode 100644
index 0000000..e374e64
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver.c
@@ -0,0 +1,1134 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbdriver.h"
37#include "imfcache.h"
38#include "generic_cache.h"
39#include "libetpan-config.h"
40#include "dbdriver_message.h"
41#include "mail_cache_db.h"
42#include <string.h>
43#include <stdlib.h>
44#include "mailmessage.h"
45
46static int initialize(mailsession * session);
47
48static void uninitialize(mailsession * session);
49
50static int connect_path(mailsession * session, char * path);
51
52static int logout(mailsession * session);
53
54static int expunge_folder(mailsession * session);
55
56static int status_folder(mailsession * session, char * mb,
57 uint32_t * result_messages, uint32_t * result_recent,
58 uint32_t * result_unseen);
59
60static int recent_number(mailsession * session, char * mb,
61 uint32_t * result);
62
63static int unseen_number(mailsession * session, char * mb,
64 uint32_t * result);
65
66static int messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int append_message(mailsession * session,
70 char * message, size_t size);
71
72static int append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int get_messages_list(mailsession * session,
76 struct mailmessage_list ** result);
77
78static int get_envelopes_list(mailsession * session,
79 struct mailmessage_list * env_list);
80
81static int check_folder(mailsession * session);
82
83static int get_message(mailsession * session,
84 uint32_t num, mailmessage ** result);
85
86static int get_message_by_uid(mailsession * session,
87 const char * uid, mailmessage ** result);
88
89static mailsession_driver local_db_session_driver = {
90 .sess_name = "db",
91
92 .sess_initialize = initialize,
93 .sess_uninitialize = uninitialize,
94
95 .sess_parameters = NULL,
96
97 .sess_connect_stream = NULL,
98 .sess_connect_path = connect_path,
99 .sess_starttls = NULL,
100 .sess_login = NULL,
101 .sess_logout = logout,
102 .sess_noop = NULL,
103
104 .sess_build_folder_name = NULL,
105 .sess_create_folder = NULL,
106 .sess_delete_folder = NULL,
107 .sess_rename_folder = NULL,
108 .sess_check_folder = check_folder,
109 .sess_examine_folder = NULL,
110 .sess_select_folder = NULL,
111 .sess_expunge_folder = expunge_folder,
112 .sess_status_folder = status_folder,
113 .sess_messages_number = messages_number,
114 .sess_recent_number = recent_number,
115 .sess_unseen_number = unseen_number,
116 .sess_list_folders = NULL,
117 .sess_lsub_folders = NULL,
118 .sess_subscribe_folder = NULL,
119 .sess_unsubscribe_folder = NULL,
120
121 .sess_append_message = append_message,
122 .sess_append_message_flags = append_message_flags,
123 .sess_copy_message = NULL,
124 .sess_move_message = NULL,
125
126 .sess_get_messages_list = get_messages_list,
127 .sess_get_envelopes_list = get_envelopes_list,
128 .sess_remove_message = NULL,
129
130 .sess_get_message = get_message,
131 .sess_get_message_by_uid = get_message_by_uid,
132};
133
134mailsession_driver * db_session_driver = &local_db_session_driver;
135
136static inline struct db_session_state_data * get_data(mailsession * session)
137{
138 return session->sess_data;
139}
140
141static int flags_store_process(mailsession * session)
142{
143 unsigned int i;
144 MMAPString * mmapstr;
145 int r;
146 int res;
147 struct mail_cache_db * maildb;
148 struct db_session_state_data * data;
149 struct mail_flags_store * flags_store;
150
151 data = get_data(session);
152
153 flags_store = data->db_flags_store;
154
155 if (carray_count(flags_store->fls_tab) == 0)
156 return MAIL_NO_ERROR;
157
158 mmapstr = mmap_string_new("");
159 if (mmapstr == NULL) {
160 res = MAIL_ERROR_MEMORY;
161 goto err;
162 }
163
164 r = mail_cache_db_open_lock(data->db_filename, &maildb);
165 if (r < 0) {
166 res = MAIL_ERROR_FILE;
167 goto free_mmapstr;
168 }
169
170 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
171 mailmessage * msg;
172 char key[PATH_MAX];
173
174 msg = carray_get(flags_store->fls_tab, i);
175
176 snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index);
177
178 r = generic_cache_flags_write(maildb, mmapstr,
179 key, msg->msg_flags);
180 }
181
182 mail_flags_store_clear(flags_store);
183
184 mail_cache_db_close_unlock(data->db_filename, maildb);
185 mmap_string_free(mmapstr);
186
187 return MAIL_NO_ERROR;
188
189 free_mmapstr:
190 mmap_string_free(mmapstr);
191 err:
192 return res;
193}
194
195static int db_get_next_validity(struct mail_cache_db * maildb,
196 uint32_t * p_validity)
197{
198 int r;
199 char key_value[PATH_MAX];
200 uint32_t validity;
201 void * serialized;
202 size_t serialized_len;
203 int res;
204 MMAPString * mmapstr;
205 size_t cur_token;
206
207 mmapstr = mmap_string_new_len(serialized, serialized_len);
208 if (mmapstr == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213 snprintf(key_value, sizeof(key_value), "next-validity");
214
215 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
216 &serialized, &serialized_len);
217
218 if (r >= 0) {
219 size_t cur_token;
220
221 cur_token = 0;
222 r = mailimf_cache_int_read(mmapstr, &cur_token, &validity);
223 if (r < 0)
224 validity = 0;
225 }
226 else {
227 validity = 0;
228 }
229
230 mmap_string_set_size(mmapstr, 0);
231 cur_token = 0;
232 r = mailimf_cache_int_write(mmapstr, &cur_token, validity + 1);
233 if (r < 0) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_mmapstr;
236 }
237
238 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
239 mmapstr->str, mmapstr->len);
240 if (r < 0) {
241 res = MAIL_ERROR_FILE;
242 goto free_mmapstr;
243 }
244
245 mmap_string_free(mmapstr);
246
247 * p_validity = validity;
248
249 return MAIL_NO_ERROR;
250
251 free_mmapstr:
252 mmap_string_free(mmapstr);
253 err:
254 return res;
255}
256
257static int db_get_next_msg_number(struct mail_cache_db * maildb,
258 uint32_t * p_num)
259{
260 int r;
261 char key_value[PATH_MAX];
262 uint32_t num;
263 void * serialized;
264 size_t serialized_len;
265 int res;
266 MMAPString * mmapstr;
267 size_t cur_token;
268
269 mmapstr = mmap_string_new("");
270 if (mmapstr == NULL) {
271 res = MAIL_ERROR_MEMORY;
272 goto err;
273 }
274
275 snprintf(key_value, sizeof(key_value), "next-msg");
276
277 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
278 &serialized, &serialized_len);
279
280 if (r >= 0) {
281 size_t cur_token;
282
283 if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) {
284 res = MAIL_ERROR_MEMORY;
285 goto err;
286 }
287
288 cur_token = 0;
289 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
290 if (r < 0)
291 num = 1;
292 }
293 else {
294 num = 1;
295 }
296
297 mmap_string_set_size(mmapstr, 0);
298 cur_token = 0;
299 r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1);
300 if (r < 0) {
301 res = MAIL_ERROR_MEMORY;
302 goto free_mmapstr;
303 }
304
305 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
306 mmapstr->str, mmapstr->len);
307 if (r < 0) {
308 res = MAIL_ERROR_FILE;
309 goto free_mmapstr;
310 }
311
312 mmap_string_free(mmapstr);
313
314 * p_num = num;
315
316 return MAIL_NO_ERROR;
317
318 free_mmapstr:
319 mmap_string_free(mmapstr);
320 err:
321 return res;
322}
323
324static int db_set_message_list(struct mail_cache_db * maildb,
325 carray * msglist)
326{
327 MMAPString * mmapstr;
328 char key_value[PATH_MAX];
329 int r;
330 unsigned int i;
331 size_t cur_token;
332 int res;
333
334 mmapstr = mmap_string_new("");
335 if (mmapstr == NULL) {
336 res = MAIL_ERROR_MEMORY;
337 goto err;
338 }
339
340 cur_token = 0;
341 for(i = 0 ; i < carray_count(msglist) ; i ++) {
342 uint32_t * msg;
343
344 msg = carray_get(msglist, i);
345 r = mailimf_cache_int_write(mmapstr, &cur_token, * msg);
346 if (r != MAIL_NO_ERROR) {
347 res = r;
348 goto free_mmapstr;
349 }
350 }
351
352 snprintf(key_value, sizeof(key_value), "message-list");
353 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
354 mmapstr->str, mmapstr->len);
355 if (r < 0) {
356 res = MAIL_ERROR_FILE;
357 goto err;
358 }
359
360 mmap_string_free(mmapstr);
361
362 return MAIL_NO_ERROR;
363
364 free_mmapstr:
365 mmap_string_free(mmapstr);
366 err:
367 return res;
368}
369
370static int db_get_message_list(struct mail_cache_db * maildb,
371 carray ** p_msglist)
372{
373 carray * msglist;
374 void * serialized;
375 size_t serialized_len;
376 int r;
377 char key_value[PATH_MAX];
378 int res;
379 unsigned int i;
380
381 msglist = carray_new(16);
382 if (msglist == NULL) {
383 res = MAIL_ERROR_MEMORY;
384 goto err;
385 }
386
387 snprintf(key_value, sizeof(key_value), "message-list");
388 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
389 &serialized, &serialized_len);
390 if (r >= 0) {
391 MMAPString * mmapstr;
392 size_t cur_token;
393
394 /* collect message list */
395
396 mmapstr = mmap_string_new_len(serialized, serialized_len);
397 if (mmapstr == NULL) {
398 res = MAIL_ERROR_MEMORY;
399 goto free_msglist;
400 }
401
402 cur_token = 0;
403 do {
404 uint32_t num;
405 uint32_t * msg;
406
407 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
408 if (r != MAIL_NO_ERROR)
409 break;
410
411 msg = malloc(sizeof(* msg));
412 if (msg == NULL) {
413 res = MAIL_ERROR_MEMORY;
414 mmap_string_free(mmapstr);
415 goto free_msglist;
416 }
417 * msg = num;
418
419 r = carray_add(msglist, msg, NULL);
420 if (r < 0) {
421 res = MAIL_ERROR_MEMORY;
422 free(msg);
423 mmap_string_free(mmapstr);
424 goto free_msglist;
425 }
426 } while (1);
427
428 mmap_string_free(mmapstr);
429 }
430
431 * p_msglist = msglist;
432
433 return MAIL_NO_ERROR;
434
435 free_msglist:
436 for(i = 0 ; i < carray_count(msglist) ; i ++) {
437 uint32_t * msg;
438
439 msg = carray_get(msglist, i);
440 free(msg);
441 }
442 carray_free(msglist);
443 err:
444 return res;
445}
446
447static int initialize(mailsession * session)
448{
449 struct db_session_state_data * data;
450
451 data = malloc(sizeof(* data));
452 if (data == NULL)
453 goto err;
454
455 data->db_filename[0] = '\0';
456
457 data->db_flags_store = mail_flags_store_new();
458 if (data->db_flags_store == NULL)
459 goto free;
460
461 session->sess_data = data;
462
463 return MAIL_NO_ERROR;
464
465 free:
466 free(data);
467 err:
468 return MAIL_ERROR_MEMORY;
469}
470
471static void uninitialize(mailsession * session)
472{
473 struct db_session_state_data * data;
474
475 data = get_data(session);
476
477 flags_store_process(session);
478
479 mail_flags_store_free(data->db_flags_store);
480
481 free(data);
482
483 session->sess_data = NULL;
484}
485
486static int connect_path(mailsession * session, char * path)
487{
488 struct db_session_state_data * data;
489
490 data = get_data(session);
491
492 strncpy(data->db_filename, path, sizeof(data->db_filename));
493
494 return MAIL_NO_ERROR;
495}
496
497static int logout(mailsession * session)
498{
499 return MAIL_NO_ERROR;
500}
501
502static int expunge_folder(mailsession * session)
503{
504 int r;
505 char key_value[PATH_MAX];
506 struct mail_cache_db * maildb;
507 carray * msglist;
508 unsigned int i;
509 struct db_session_state_data * data;
510 int res;
511 chash * msg_table;
512 MMAPString * mmapstr;
513
514 data = get_data(session);
515
516 flags_store_process(session);
517
518 r = mail_cache_db_open_lock(data->db_filename, &maildb);
519 if (r < 0) {
520 res = MAIL_ERROR_FILE;
521 goto err;
522 }
523
524 r = db_get_message_list(maildb, &msglist);
525 if (r != MAIL_NO_ERROR) {
526 res = r;
527 goto close_db;
528 }
529
530 msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
531 if (msg_table == NULL) {
532 res = MAIL_ERROR_MEMORY;
533 goto free_msglist;
534 }
535
536 mmapstr = mmap_string_new("");
537 if (mmapstr == NULL) {
538 res = MAIL_ERROR_MEMORY;
539 goto free_msgtable;
540 }
541
542 i = 0;
543 while (i < carray_count(msglist)) {
544 uint32_t num;
545 uint32_t * msg;
546 chashdatum key;
547 chashdatum value;
548 struct mail_flags * flags;
549 int deleted;
550
551 msg = carray_get(msglist, i);
552 num = * msg;
553
554 deleted = 0;
555 snprintf(key_value, sizeof(key_value), "%lu-flags",
556 (unsigned long) num);
557 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
558 if (r == MAIL_NO_ERROR) {
559 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0)
560 deleted = 1;
561 }
562
563 if (!deleted) {
564 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
565 key.data = key_value;
566 key.len = strlen(key_value);
567 chash_set(msg_table, &key, &value, NULL);
568
569 snprintf(key_value, sizeof(key_value), "%lu-envelope",
570 (unsigned long) num);
571 key.data = key_value;
572 key.len = strlen(key_value);
573 chash_set(msg_table, &key, &value, NULL);
574
575 snprintf(key_value, sizeof(key_value), "%lu-flags",
576 (unsigned long) num);
577 key.data = key_value;
578 key.len = strlen(key_value);
579 chash_set(msg_table, &key, &value, NULL);
580
581 i ++;
582 }
583 else {
584 free(msg);
585 carray_delete(msglist, i);
586 }
587 }
588
589 mmap_string_free(mmapstr);
590
591 r = mail_cache_db_clean_up(maildb, msg_table);
592
593 chash_free(msg_table);
594
595 r = db_set_message_list(maildb, msglist);
596
597 for(i = 0 ; i < carray_count(msglist) ; i ++) {
598 uint32_t * msg;
599
600 msg = carray_get(msglist, i);
601 free(msg);
602 }
603 carray_free(msglist);
604
605 mail_cache_db_close_unlock(data->db_filename, maildb);
606
607 return MAIL_NO_ERROR;
608
609 free_msgtable:
610 chash_free(msg_table);
611 free_msglist:
612 for(i = 0 ; i < carray_count(msglist) ; i ++) {
613 uint32_t * msg;
614
615 msg = carray_get(msglist, i);
616 free(msg);
617 }
618 close_db:
619 mail_cache_db_close_unlock(data->db_filename, maildb);
620 err:
621 return res;
622}
623
624static int status_folder(mailsession * session, char * mb,
625 uint32_t * result_messages, uint32_t * result_recent,
626 uint32_t * result_unseen)
627{
628 struct mail_cache_db * maildb;
629 char key_value[PATH_MAX];
630 MMAPString * mmapstr;
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 struct db_session_state_data * data;
635 int r;
636 int res;
637 carray * msglist;
638 unsigned int i;
639
640 data = get_data(session);
641
642 flags_store_process(session);
643
644 r = mail_cache_db_open_lock(data->db_filename, &maildb);
645 if (r < 0) {
646 res = MAIL_ERROR_FILE;
647 goto err;
648 }
649
650 r = db_get_message_list(maildb, &msglist);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto close_db;
654 }
655
656 mmapstr = mmap_string_new("");
657 if (mmapstr == NULL) {
658 res = MAIL_ERROR_MEMORY;
659 goto free_list;
660 }
661
662 messages = 0;
663 recent = 0;
664 unseen = 0;
665 for(i = 0 ; i < carray_count(msglist) ; i ++) {
666 uint32_t num;
667 uint32_t * msg;
668 int r;
669 struct mail_flags * flags;
670
671 msg = carray_get(msglist, i);
672 num = * msg;
673 free(msg);
674 carray_set(msglist, i, NULL);
675
676 messages ++;
677
678 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
679
680 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
681 if (r == MAIL_NO_ERROR) {
682 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
683 recent ++;
684 }
685 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
686 unseen ++;
687 }
688 mail_flags_free(flags);
689 }
690 }
691
692 mmap_string_free(mmapstr);
693
694 carray_free(msglist);
695
696 mail_cache_db_close_unlock(data->db_filename, maildb);
697
698 * result_messages = messages;
699 * result_unseen = unseen;
700 * result_recent = recent;
701
702 return MAIL_NO_ERROR;
703
704 free_list:
705 for(i = 0 ; i < carray_count(msglist) ; i ++) {
706 uint32_t * msg;
707
708 msg = carray_get(msglist, i);
709 if (msg != NULL)
710 free(msg);
711 }
712 carray_free(msglist);
713 close_db:
714 mail_cache_db_close_unlock(data->db_filename, maildb);
715 err:
716 return res;
717}
718
719static int recent_number(mailsession * session, char * mb,
720 uint32_t * result)
721{
722 uint32_t dummy_messages;
723 uint32_t dummy_unseen;
724
725 return status_folder(session, mb,
726 &dummy_messages, result, &dummy_unseen);
727}
728
729static int unseen_number(mailsession * session, char * mb,
730 uint32_t * result)
731{
732 uint32_t dummy_messages;
733 uint32_t dummy_recent;
734
735 return status_folder(session, mb,
736 &dummy_messages, &dummy_recent, result);
737}
738
739static int messages_number(mailsession * session, char * mb,
740 uint32_t * result)
741{
742 uint32_t dummy_unseen;
743 uint32_t dummy_recent;
744
745 return status_folder(session, mb,
746 result, &dummy_recent, &dummy_unseen);
747}
748
749static int append_message(mailsession * session,
750 char * message, size_t size)
751{
752 return append_message_flags(session, message, size, NULL);
753}
754
755static int append_message_flags(mailsession * session,
756 char * message, size_t size, struct mail_flags * flags)
757{
758 carray * msglist;
759 unsigned int i;
760 uint32_t * msg;
761 uint32_t num;
762 char key_value[PATH_MAX];
763 MMAPString * mmapstr;
764 struct mail_cache_db * maildb;
765 struct db_session_state_data * data;
766 size_t cur_token;
767 struct mailimf_fields * fields;
768 int r;
769 int res;
770
771 data = get_data(session);
772
773 r = mail_cache_db_open_lock(data->db_filename, &maildb);
774 if (r < 0) {
775 res = MAIL_ERROR_FILE;
776 goto err;
777 }
778
779 r = db_get_next_msg_number(maildb, &num);
780 if (r != MAIL_NO_ERROR) {
781 res = r;
782 goto err;
783 }
784
785 r = db_get_message_list(maildb, &msglist);
786 if (r != MAIL_NO_ERROR) {
787 res = r;
788 goto close_db;
789 }
790
791 msg = malloc(sizeof(* msg));
792 if (msg == NULL) {
793 res = MAIL_ERROR_MEMORY;
794 goto free_msglist;
795 }
796
797 * msg = num;
798
799 r = carray_add(msglist, msg, NULL);
800 if (r < 0) {
801 res = MAIL_ERROR_MEMORY;
802 free(msg);
803 goto free_msglist;
804 }
805
806 r = db_set_message_list(maildb, msglist);
807 if (r != MAIL_NO_ERROR) {
808 res = r;
809 goto free_msglist;
810 }
811
812 /* free msglist */
813
814 for(i = 0 ; i < carray_count(msglist) ; i ++) {
815 uint32_t * msg;
816
817 msg = carray_get(msglist, i);
818 free(msg);
819 }
820 carray_free(msglist);
821
822 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
823
824 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
825 message, size);
826 if (r < 0) {
827 res = MAIL_ERROR_FILE;
828 goto close_db;
829 }
830
831 /* write envelope */
832
833 cur_token = 0;
834 r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields);
835 if (r != MAILIMF_NO_ERROR) {
836 res = MAIL_ERROR_PARSE;
837 goto close_db;
838 }
839
840 mmapstr = mmap_string_new("");
841 if (mmapstr == NULL) {
842 res = MAIL_ERROR_MEMORY;
843 goto close_db;
844 }
845
846 cur_token = 0;
847 r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
848 if (r != MAIL_NO_ERROR) {
849 res = r;
850 mmap_string_free(mmapstr);
851 goto close_db;
852 }
853
854 snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num);
855
856 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
857 mmapstr->str, mmapstr->len);
858
859 mmap_string_free(mmapstr);
860
861 mailimf_fields_free(fields);
862
863 /* write flags */
864
865 if (flags != NULL) {
866 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
867
868 mmapstr = mmap_string_new("");
869 if (mmapstr == NULL) {
870 res = MAIL_ERROR_MEMORY;
871 goto close_db;
872 }
873
874 r = generic_cache_flags_write(maildb, mmapstr,
875 key_value, flags);
876
877 mmap_string_free(mmapstr);
878
879 if (r != MAIL_NO_ERROR) {
880 res = MAIL_ERROR_FILE;
881 goto close_db;
882 }
883 }
884
885 mail_cache_db_close_unlock(data->db_filename, maildb);
886
887 return MAIL_NO_ERROR;
888
889 free_msglist:
890 for(i = 0 ; i < carray_count(msglist) ; i ++) {
891 uint32_t * msg;
892
893 msg = carray_get(msglist, i);
894 free(msg);
895 }
896 carray_free(msglist);
897 close_db:
898 mail_cache_db_close_unlock(data->db_filename, maildb);
899 err:
900 return res;
901}
902
903static int get_messages_list(mailsession * session,
904 struct mailmessage_list ** result)
905{
906 int r;
907 char key[PATH_MAX];
908 struct mail_cache_db * maildb;
909 struct db_session_state_data * data;
910 int res;
911 carray * msglist;
912 unsigned int i;
913 carray * msgtab;
914 struct mailmessage_list * driver_msglist;
915
916 data = get_data(session);
917
918 r = mail_cache_db_open_lock(data->db_filename, &maildb);
919 if (r < 0) {
920 res = MAIL_ERROR_FILE;
921 goto err;
922 }
923
924 r = db_get_message_list(maildb, &msglist);
925 if (r != MAIL_NO_ERROR) {
926 res = r;
927 goto close_db;
928 }
929
930 msgtab = carray_new(16);
931 if (msgtab == NULL) {
932 res = MAIL_ERROR_MEMORY;
933 goto close_db;
934 }
935
936 for(i = 0 ; i < carray_count(msglist) ; i ++) {
937 uint32_t msg_num;
938 uint32_t * pmsg_num;
939 mailmessage * msg;
940 size_t size;
941
942 pmsg_num = carray_get(msglist, i);
943 msg_num = * pmsg_num;
944 free(pmsg_num);
945 carray_set(msglist, i, NULL);
946
947 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num);
948 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
949 if (r < 0) {
950 continue;
951 }
952
953 msg = mailmessage_new();
954 if (msg == NULL) {
955 res = MAIL_ERROR_MEMORY;
956 goto free_list;
957 }
958
959 r = mailmessage_init(msg, session, db_message_driver,
960 msg_num, size);
961 if (r != MAIL_NO_ERROR) {
962 mailmessage_free(msg);
963 res = r;
964 goto free_list;
965 }
966
967 r = carray_add(msgtab, msg, NULL);
968 if (r < 0) {
969 mailmessage_free(msg);
970 res = MAIL_ERROR_MEMORY;
971 goto free_list;
972 }
973 }
974 carray_free(msglist);
975
976 driver_msglist = mailmessage_list_new(msgtab);
977 if (driver_msglist == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto free_list;
980 }
981
982 mail_cache_db_close_unlock(data->db_filename, maildb);
983
984 * result = driver_msglist;
985
986 return MAIL_NO_ERROR;
987
988 free_list:
989 for(i = 0 ; i < carray_count(msgtab) ; i ++) {
990 mailmessage * msg;
991
992 msg = carray_get(msgtab, i);
993 mailmessage_free(msg);
994 }
995 carray_free(msgtab);
996
997 for(i = 0 ; i < carray_count(msglist) ; i ++) {
998 uint32_t * msg;
999
1000 msg = carray_get(msglist, i);
1001 if (msg != NULL)
1002 free(msg);
1003 }
1004 carray_free(msglist);
1005 close_db:
1006 mail_cache_db_close_unlock(data->db_filename, maildb);
1007 err:
1008 return res;
1009}
1010
1011static int get_envelopes_list(mailsession * session,
1012 struct mailmessage_list * env_list)
1013{
1014 unsigned int i;
1015 char key[PATH_MAX];
1016 int r;
1017 struct mail_cache_db * maildb;
1018 int res;
1019 struct db_session_state_data * data;
1020 MMAPString * mmapstr;
1021
1022 data = get_data(session);
1023
1024 flags_store_process(session);
1025
1026 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1027 if (r < 0) {
1028 res = MAIL_ERROR_FILE;
1029 goto err;
1030 }
1031
1032 mmapstr = mmap_string_new("");
1033 if (mmapstr == NULL) {
1034 res = MAIL_ERROR_MEMORY;
1035 goto close_db;
1036 }
1037
1038 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1039 mailmessage * msg;
1040
1041 msg = carray_get(env_list->msg_tab, i);
1042 if (msg->msg_fields == NULL) {
1043 snprintf(key, sizeof(key), "%lu-envelope",
1044 (unsigned long) msg->msg_index);
1045
1046 r = generic_cache_fields_read(maildb, mmapstr,
1047 key, &msg->msg_fields);
1048 }
1049
1050 if (msg->msg_flags == NULL) {
1051 snprintf(key, sizeof(key), "%lu-flags",
1052 (unsigned long) msg->msg_index);
1053
1054 r = generic_cache_flags_read(maildb, mmapstr,
1055 key, &msg->msg_flags);
1056 }
1057 }
1058
1059 mmap_string_free(mmapstr);
1060
1061 mail_cache_db_close_unlock(data->db_filename, maildb);
1062
1063 return MAIL_NO_ERROR;
1064
1065 close_db:
1066 mail_cache_db_close_unlock(data->db_filename, maildb);
1067 err:
1068 return res;
1069}
1070
1071static int check_folder(mailsession * session)
1072{
1073 flags_store_process(session);
1074
1075 return MAIL_NO_ERROR;
1076}
1077
1078static int get_message(mailsession * session,
1079 uint32_t num, mailmessage ** result)
1080{
1081 mailmessage * msg;
1082 int r;
1083 size_t size;
1084 char key[PATH_MAX];
1085 struct db_session_state_data * data;
1086 struct mail_cache_db * maildb;
1087 int res;
1088
1089 data = get_data(session);
1090
1091 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1092 if (r < 0) {
1093 res = MAIL_ERROR_FILE;
1094 goto err;
1095 }
1096
1097 msg = mailmessage_new();
1098 if (msg == NULL) {
1099 res = MAIL_ERROR_MEMORY;
1100 goto close_db;
1101 }
1102
1103 size = 0;
1104 snprintf(key, sizeof(key), "%lu", (unsigned long) num);
1105 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
1106 /* ignore error */
1107
1108 r = mailmessage_init(msg, session, db_message_driver,
1109 num, size);
1110 if (r != MAIL_NO_ERROR) {
1111 mailmessage_free(msg);
1112 res = r;
1113 goto close_db;
1114 }
1115
1116 mail_cache_db_close_unlock(data->db_filename, maildb);
1117
1118 return MAIL_NO_ERROR;
1119
1120 close_db:
1121 mail_cache_db_close_unlock(data->db_filename, maildb);
1122 err:
1123 return res;
1124}
1125
1126static int get_message_by_uid(mailsession * session,
1127 const char * uid, mailmessage ** result)
1128{
1129 uint32_t msg_num;
1130
1131 msg_num = strtoul(uid, NULL, 10);
1132
1133 return get_message(session, msg_num, result);
1134}
diff --git a/libetpan/src/driver/implementation/db/dbdriver.h b/libetpan/src/driver/implementation/db/dbdriver.h
new file mode 100644
index 0000000..1c2a96d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_H
37
38#define DBDRIVER_H
39
40#include <libetpan/dbdriver_message.h>
41#include <libetpan/dbdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * db_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver_message.c b/libetpan/src/driver/implementation/db/dbdriver_message.c
new file mode 100644
index 0000000..70e9dca
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_message.c
@@ -0,0 +1,308 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbdriver_message.h"
37#include "dbdriver.h"
38#include "mail_cache_db.h"
39
40#include "mailmessage_tools.h"
41#include "generic_cache.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int fetch_envelope(mailmessage * msg_info,
52 struct mailimf_fields ** result);
53
54static int get_flags(mailmessage * msg_info,
55 struct mail_flags ** result);
56
57static int prefetch(mailmessage * msg_info);
58
59static void prefetch_free(struct generic_message_t * msg);
60
61static int initialize(mailmessage * msg_info);
62
63static void check(mailmessage * msg_info);
64
65static mailmessage_driver local_db_message_driver = {
66 .msg_name = "db",
67
68 .msg_initialize = initialize,
69 .msg_uninitialize = mailmessage_generic_uninitialize,
70
71 .msg_flush = mailmessage_generic_flush,
72 .msg_check = check,
73
74 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
75
76 .msg_fetch = mailmessage_generic_fetch,
77 .msg_fetch_header = mailmessage_generic_fetch_header,
78 .msg_fetch_body = mailmessage_generic_fetch_header,
79 .msg_fetch_size = NULL,
80 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
81 .msg_fetch_section = mailmessage_generic_fetch_section,
82 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
83 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
84 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
85 .msg_fetch_envelope = fetch_envelope,
86
87 .msg_get_flags = get_flags,
88};
89
90mailmessage_driver * db_message_driver = &local_db_message_driver;
91
92struct db_msg_data {
93 MMAPString * msg_content;
94};
95
96static inline struct db_session_state_data *
97get_session_data(mailmessage * msg)
98{
99 return msg->msg_session->sess_data;
100}
101
102static int prefetch(mailmessage * msg_info)
103{
104 struct generic_message_t * msg;
105 int res;
106 struct db_msg_data * data;
107 struct db_session_state_data * sess_data;
108 MMAPString * msg_content;
109 struct mail_cache_db * maildb;
110 int r;
111 char key[PATH_MAX];
112 void * msg_data;
113 size_t msg_data_len;
114
115 sess_data = get_session_data(msg_info);
116
117 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
118 if (r < 0) {
119 res = MAIL_ERROR_FILE;
120 goto err;
121 }
122
123 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
124 r = mail_cache_db_get(maildb, key, strlen(key), &msg_data, &msg_data_len);
125 if (r < 0) {
126 res = MAIL_ERROR_MSG_NOT_FOUND;
127 goto close_db;
128 }
129
130 msg_content = mmap_string_new_len(msg_data, msg_data_len);
131 if (msg_content == NULL) {
132 res = MAIL_ERROR_MEMORY;
133 goto close_db;
134 }
135
136 data = malloc(sizeof(* data));
137 if (data == NULL) {
138 res = MAIL_ERROR_MEMORY;
139 goto free_mmapstr;
140 }
141
142 data->msg_content = msg_content;
143
144 msg = msg_info->msg_data;
145
146 msg->msg_data = data;
147 msg->msg_message = msg_content->str;
148 msg->msg_length = msg_content->len;
149
150 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
151
152 return MAIL_NO_ERROR;
153
154 free_mmapstr:
155 mmap_string_free(msg_content);
156 close_db:
157 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
158 err:
159 return res;
160}
161
162static void prefetch_free(struct generic_message_t * msg)
163{
164 if (msg->msg_message != NULL) {
165 struct db_msg_data * data;
166
167 data = msg->msg_data;
168 mmap_string_free(data->msg_content);
169 data->msg_content = NULL;
170 free(data);
171 msg->msg_message = NULL;
172 }
173}
174
175static int initialize(mailmessage * msg_info)
176{
177 struct generic_message_t * msg;
178 int r;
179 char key[PATH_MAX];
180
181 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index);
182 msg_info->msg_uid = strdup(key);
183 if (msg_info->msg_uid == NULL)
184 return MAIL_ERROR_MEMORY;
185
186 r = mailmessage_generic_initialize(msg_info);
187 if (r != MAIL_NO_ERROR)
188 return r;
189
190 msg = msg_info->msg_data;
191 msg->msg_prefetch = prefetch;
192 msg->msg_prefetch_free = prefetch_free;
193
194 return MAIL_NO_ERROR;
195}
196
197static void check(mailmessage * msg_info)
198{
199 int r;
200
201 if (msg_info->msg_flags != NULL) {
202 r = mail_flags_store_set(get_session_data(msg_info)->db_flags_store,
203 msg_info);
204 /* ignore errors */
205 }
206}
207
208static int fetch_envelope(mailmessage * msg_info,
209 struct mailimf_fields ** result)
210{
211 char key[PATH_MAX];
212 int r;
213 struct db_session_state_data * sess_data;
214 struct mail_cache_db * maildb;
215 int res;
216 struct mailimf_fields * fields;
217 MMAPString * mmapstr;
218
219 sess_data = get_session_data(msg_info);
220
221 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
222 if (r < 0) {
223 res = MAIL_ERROR_FILE;
224 goto err;
225 }
226
227 snprintf(key, sizeof(key), "%lu-envelope",
228 (unsigned long) msg_info->msg_index);
229
230 mmapstr = mmap_string_new("");
231 if (mmapstr == NULL) {
232 res = MAIL_ERROR_MEMORY;
233 goto close_db;
234 }
235
236 r = generic_cache_fields_read(maildb, mmapstr,
237 key, &fields);
238
239 mmap_string_free(mmapstr);
240
241 if (r != MAIL_NO_ERROR) {
242 res = MAIL_ERROR_MSG_NOT_FOUND;
243 goto close_db;
244 }
245
246 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
247
248 * result = fields;
249
250 return MAIL_NO_ERROR;
251
252 close_db:
253 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
254 err:
255 return res;
256}
257
258static int get_flags(mailmessage * msg_info,
259 struct mail_flags ** result)
260{
261 char key[PATH_MAX];
262 int r;
263 struct db_session_state_data * sess_data;
264 struct mail_cache_db * maildb;
265 int res;
266 MMAPString * mmapstr;
267
268 sess_data = get_session_data(msg_info);
269
270 r = mail_cache_db_open_lock(sess_data->db_filename, &maildb);
271 if (r < 0) {
272 res = MAIL_ERROR_FILE;
273 goto err;
274 }
275
276 snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg_info->msg_index);
277
278 mmapstr = mmap_string_new("");
279 if (mmapstr == NULL) {
280 res = MAIL_ERROR_MEMORY;
281 goto close_db;
282 }
283
284 r = generic_cache_flags_read(maildb, mmapstr,
285 key, &msg_info->msg_flags);
286
287 mmap_string_free(mmapstr);
288
289 if (r != MAIL_NO_ERROR) {
290 msg_info->msg_flags = mail_flags_new_empty();
291 if (msg_info->msg_flags == NULL) {
292 res = MAIL_ERROR_MEMORY;
293 goto close_db;
294 }
295 }
296
297 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
298
299 * result = msg_info->msg_flags;
300
301 return MAIL_NO_ERROR;
302
303 close_db:
304 mail_cache_db_close_unlock(sess_data->db_filename, maildb);
305 err:
306 return res;
307}
308
diff --git a/libetpan/src/driver/implementation/db/dbdriver_message.h b/libetpan/src/driver/implementation/db/dbdriver_message.h
new file mode 100644
index 0000000..f634775
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_MESSAGE_H
37
38#define DBDRIVER_MESSAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * db_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/db/dbdriver_types.h b/libetpan/src/driver/implementation/db/dbdriver_types.h
new file mode 100644
index 0000000..052e3db
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver_types.h
@@ -0,0 +1,71 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBDRIVER_TYPES_H
37
38#define DBDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/generic_cache_types.h>
44#include <libetpan/mailstorage_types.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
50struct db_session_state_data {
51 char db_filename[PATH_MAX];
52 struct mail_flags_store * db_flags_store;
53};
54
55/* db storage */
56
57/*
58 db_mailstorage is the state data specific to the db storage.
59
60 - pathname is the path of the db storage.
61*/
62
63struct db_mailstorage {
64 char * db_pathname;
65};
66
67#ifdef __cplusplus
68}
69#endif
70
71#endif
diff --git a/libetpan/src/driver/implementation/db/dbstorage.c b/libetpan/src/driver/implementation/db/dbstorage.c
new file mode 100644
index 0000000..c4be63c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbstorage.c
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "dbstorage.h"
37#include "mailstorage.h"
38
39#include "mail.h"
40#include "mailmessage.h"
41#include "dbdriver.h"
42#include "maildriver.h"
43
44#include <stdlib.h>
45#include <string.h>
46
47/* db storage */
48
49static int db_mailstorage_connect(struct mailstorage * storage);
50static int
51db_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void db_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver db_mailstorage_driver = {
56 .sto_name = "db",
57 .sto_connect = db_mailstorage_connect,
58 .sto_get_folder_session = db_mailstorage_get_folder_session,
59 .sto_uninitialize = db_mailstorage_uninitialize,
60};
61
62int db_mailstorage_init(struct mailstorage * storage,
63 char * db_pathname)
64{
65 struct db_mailstorage * db_storage;
66
67 db_storage = malloc(sizeof(* db_storage));
68 if (db_storage == NULL)
69 goto err;
70
71 db_storage->db_pathname = strdup(db_pathname);
72 if (db_storage->db_pathname == NULL)
73 goto free;
74
75 storage->sto_data = db_storage;
76 storage->sto_driver = &db_mailstorage_driver;
77
78 return MAIL_NO_ERROR;
79
80 free:
81 free(db_storage);
82 err:
83 return MAIL_ERROR_MEMORY;
84}
85
86static void db_mailstorage_uninitialize(struct mailstorage * storage)
87{
88 struct db_mailstorage * db_storage;
89
90 db_storage = storage->sto_data;
91 free(db_storage->db_pathname);
92 free(db_storage);
93
94 storage->sto_data = NULL;
95}
96
97static int db_mailstorage_connect(struct mailstorage * storage)
98{
99 struct db_mailstorage * db_storage;
100 mailsession_driver * driver;
101 int r;
102 int res;
103 mailsession * session;
104
105 db_storage = storage->sto_data;
106
107 driver = db_session_driver;
108
109 session = mailsession_new(driver);
110 if (session == NULL) {
111 res = MAIL_ERROR_MEMORY;
112 goto err;
113 }
114
115 r = mailsession_connect_path(session, db_storage->db_pathname);
116 switch (r) {
117 case MAIL_NO_ERROR_NON_AUTHENTICATED:
118 case MAIL_NO_ERROR_AUTHENTICATED:
119 case MAIL_NO_ERROR:
120 break;
121 default:
122 res = r;
123 goto free;
124 }
125
126 storage->sto_session = session;
127
128 return MAIL_NO_ERROR;
129
130 free:
131 mailsession_free(session);
132 err:
133 return res;
134}
135
136static int
137db_mailstorage_get_folder_session(struct mailstorage * storage,
138 char * pathname, mailsession ** result)
139{
140 * result = storage->sto_session;
141
142 return MAIL_NO_ERROR;
143}
144
diff --git a/libetpan/src/driver/implementation/db/dbstorage.h b/libetpan/src/driver/implementation/db/dbstorage.h
new file mode 100644
index 0000000..5fa9659
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbstorage.h
@@ -0,0 +1,61 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef DBSTORAGE_H
37
38#define DBSTORAGE_H
39
40#include <libetpan/dbdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 db_mailstorage_init is the constructor for a DB storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52*/
53
54int db_mailstorage_init(struct mailstorage * storage,
55 char * db_pathname);
56
57#ifdef __cplusplus
58}
59#endif
60
61#endif
diff --git a/libetpan/src/driver/implementation/hotmail/hotmailstorage.c b/libetpan/src/driver/implementation/hotmail/hotmailstorage.c
new file mode 100644
index 0000000..0d1503b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/hotmail/hotmailstorage.c
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "hotmailstorage.h"
37
38#include "pop3storage.h"
39#include "pop3driver_types.h"
40
41/*
42 hotway is a gateway from hotmail to POP3
43
44 http://hotwayd.sourceforge.net/
45*/
46
47static char hotway_command[512] = "/usr/bin/hotwayd";
48
49int hotmail_mailstorage_init(struct mailstorage * storage,
50 char * hotmail_login, char * hotmail_password,
51 int hotmail_cached, char * hotmail_cache_directory,
52 char * hotmail_flags_directory)
53{
54 return pop3_mailstorage_init(storage,
55 "hotmail.dummy", 0,
56 hotway_command,
57 CONNECTION_TYPE_COMMAND, POP3_AUTH_TYPE_PLAIN,
58 hotmail_login, hotmail_password,
59 hotmail_cached, hotmail_cache_directory,
60 hotmail_flags_directory);
61}
62
diff --git a/libetpan/src/driver/implementation/hotmail/hotmailstorage.h b/libetpan/src/driver/implementation/hotmail/hotmailstorage.h
new file mode 100644
index 0000000..05d6385
--- a/dev/null
+++ b/libetpan/src/driver/implementation/hotmail/hotmailstorage.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef HOTMAILSTORAGE_H
37
38#define HOTMAILSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstorage_types.h"
45
46int hotmail_mailstorage_init(struct mailstorage * storage,
47 char * hotmail_login, char * hotmail_password,
48 int hotmail_cached, char * hotmail_cache_directory,
49 char * hotmail_flags_directory);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
56
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.c b/libetpan/src/driver/implementation/imap/imapdriver.c
new file mode 100644
index 0000000..815e077
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.c
@@ -0,0 +1,1226 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver.h"
37
38#include "mail.h"
39#include "imapdriver_tools.h"
40#include "mailmessage.h"
41#include "imapdriver_message.h"
42#include "imapdriver_types.h"
43#include "maildriver.h"
44#include "maildriver_tools.h"
45#include "generic_cache.h"
46
47#include <stdlib.h>
48#include <string.h>
49
50static int imapdriver_initialize(mailsession * session);
51
52static void imapdriver_uninitialize(mailsession * session);
53
54static int imapdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int imapdriver_starttls(mailsession * session);
57
58static int imapdriver_login(mailsession * session,
59 char * userid, char * password);
60
61static int imapdriver_logout(mailsession * session);
62
63static int imapdriver_noop(mailsession * session);
64
65static int imapdriver_build_folder_name(mailsession * session, char * mb,
66 char * name, char ** result);
67
68static int imapdriver_create_folder(mailsession * session, char * mb);
69
70static int imapdriver_delete_folder(mailsession * session, char * mb);
71
72static int imapdriver_rename_folder(mailsession * session, char * mb,
73 char * new_name);
74
75static int imapdriver_check_folder(mailsession * session);
76
77static int imapdriver_examine_folder(mailsession * session, char * mb);
78
79static int imapdriver_select_folder(mailsession * session, char * mb);
80static int imapdriver_expunge_folder(mailsession * session);
81
82static int imapdriver_status_folder(mailsession * session, char * mb,
83 uint32_t * result_messages, uint32_t * result_recent,
84 uint32_t * result_unseen);
85
86static int imapdriver_messages_number(mailsession * session, char * mb,
87 uint32_t * result);
88
89static int imapdriver_recent_number(mailsession * session, char * mb,
90 uint32_t * result);
91
92static int imapdriver_unseen_number(mailsession * session, char * mb,
93 uint32_t * result);
94
95static int imapdriver_list_folders(mailsession * session, char * mb,
96 struct mail_list ** result);
97static int imapdriver_lsub_folders(mailsession * session, char * mb,
98 struct mail_list ** result);
99static int imapdriver_subscribe_folder(mailsession * session, char * mb);
100static int imapdriver_unsubscribe_folder(mailsession * session, char * mb);
101static int imapdriver_append_message(mailsession * session,
102 char * message, size_t size);
103static int imapdriver_append_message_flags(mailsession * session,
104 char * message, size_t size, struct mail_flags * flags);
105static int imapdriver_copy_message(mailsession * session,
106 uint32_t num, char * mb);
107
108static int imapdriver_get_messages_list(mailsession * session,
109 struct mailmessage_list ** result);
110
111static int
112imapdriver_get_envelopes_list(mailsession * session,
113 struct mailmessage_list * env_list);
114
115
116#if 0
117static int imapdriver_search_messages(mailsession * session, char * charset,
118 struct mail_search_key * key,
119 struct mail_search_result ** result);
120#endif
121
122static int imapdriver_get_message(mailsession * session,
123 uint32_t num, mailmessage ** result);
124
125static int imapdriver_get_message_by_uid(mailsession * session,
126 const char * uid,
127 mailmessage ** result);
128
129static mailsession_driver local_imap_session_driver = {
130 .sess_name = "imap",
131
132 .sess_initialize = imapdriver_initialize,
133 .sess_uninitialize = imapdriver_uninitialize,
134
135 .sess_parameters = NULL,
136
137 .sess_connect_stream = imapdriver_connect_stream,
138 .sess_connect_path = NULL,
139 .sess_starttls = imapdriver_starttls,
140 .sess_login = imapdriver_login,
141 .sess_logout = imapdriver_logout,
142 .sess_noop = imapdriver_noop,
143
144 .sess_build_folder_name = imapdriver_build_folder_name,
145 .sess_create_folder = imapdriver_create_folder,
146 .sess_delete_folder = imapdriver_delete_folder,
147 .sess_rename_folder = imapdriver_rename_folder,
148 .sess_check_folder = imapdriver_check_folder,
149 .sess_examine_folder = imapdriver_examine_folder,
150 .sess_select_folder = imapdriver_select_folder,
151 .sess_expunge_folder = imapdriver_expunge_folder,
152 .sess_status_folder = imapdriver_status_folder,
153 .sess_messages_number = imapdriver_messages_number,
154 .sess_recent_number = imapdriver_recent_number,
155 .sess_unseen_number = imapdriver_unseen_number,
156 .sess_list_folders = imapdriver_list_folders,
157 .sess_lsub_folders = imapdriver_lsub_folders,
158 .sess_subscribe_folder = imapdriver_subscribe_folder,
159 .sess_unsubscribe_folder = imapdriver_unsubscribe_folder,
160
161 .sess_append_message = imapdriver_append_message,
162 .sess_append_message_flags = imapdriver_append_message_flags,
163 .sess_copy_message = imapdriver_copy_message,
164 .sess_move_message = NULL,
165
166 .sess_get_messages_list = imapdriver_get_messages_list,
167 .sess_get_envelopes_list = imapdriver_get_envelopes_list,
168 .sess_remove_message = NULL,
169#if 0
170 .sess_search_messages = imapdriver_search_messages,
171#endif
172
173 .sess_get_message = imapdriver_get_message,
174 .sess_get_message_by_uid = imapdriver_get_message_by_uid,
175};
176
177mailsession_driver * imap_session_driver = &local_imap_session_driver;
178
179static inline struct imap_session_state_data * get_data(mailsession * session)
180{
181 return session->sess_data;
182}
183
184static mailimap * get_imap_session(mailsession * session)
185{
186 return get_data(session)->imap_session;
187}
188
189static int imapdriver_initialize(mailsession * session)
190{
191 struct imap_session_state_data * data;
192 mailimap * imap;
193 struct mail_flags_store * flags_store;
194
195 imap = mailimap_new(0, NULL);
196 if (imap == NULL)
197 goto err;
198
199 flags_store = mail_flags_store_new();
200 if (flags_store == NULL)
201 goto free_session;
202
203 data = malloc(sizeof(* data));
204 if (data == NULL)
205 goto free_flags_store;
206
207 data->imap_mailbox = NULL;
208 data->imap_session = imap;
209 data->imap_flags_store = flags_store;
210
211 session->sess_data = data;
212
213 return MAIL_NO_ERROR;
214
215 free_flags_store:
216 mail_flags_store_free(flags_store);
217 free_session:
218 mailimap_free(imap);
219 err:
220 return MAIL_ERROR_MEMORY;
221}
222
223static void imap_flags_store_process(mailimap * imap,
224 struct mail_flags_store * flags_store)
225{
226 unsigned int i;
227 int r;
228 mailmessage * first;
229 mailmessage * last;
230
231 mail_flags_store_sort(flags_store);
232
233 if (carray_count(flags_store->fls_tab) == 0)
234 return;
235
236 first = carray_get(flags_store->fls_tab, 0);
237 last = first;
238
239 for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) {
240 mailmessage * msg;
241
242 msg = carray_get(flags_store->fls_tab, i);
243
244 if (last->msg_index + 1 == msg->msg_index) {
245 r = mail_flags_compare(first->msg_flags, msg->msg_flags);
246 if (r == 0) {
247 last = msg;
248 continue;
249 }
250 }
251
252 r = imap_store_flags(imap, first->msg_index,
253 last->msg_index, first->msg_flags);
254
255 first = msg;
256 last = msg;
257 }
258
259 r = imap_store_flags(imap, first->msg_index, last->msg_index,
260 first->msg_flags);
261
262 mail_flags_store_clear(flags_store);
263}
264
265static void imapdriver_uninitialize(mailsession * session)
266{
267 struct imap_session_state_data * data;
268
269 data = get_data(session);
270
271 imap_flags_store_process(data->imap_session,
272 data->imap_flags_store);
273 mail_flags_store_free(data->imap_flags_store);
274
275 mailimap_free(data->imap_session);
276 if (data->imap_mailbox != NULL)
277 free(data->imap_mailbox);
278 free(data);
279
280 session->sess_data = NULL;
281}
282
283static int imapdriver_connect_stream(mailsession * session, mailstream * s)
284{
285 int r;
286
287 r = mailimap_connect(get_imap_session(session), s);
288
289 return imap_error_to_mail_error(r);
290}
291
292static int imapdriver_login(mailsession * session,
293 char * userid, char * password)
294{
295 int r;
296
297 r = mailimap_login(get_imap_session(session), userid, password);
298
299 return imap_error_to_mail_error(r);
300}
301
302static int imapdriver_logout(mailsession * session)
303{
304 int r;
305
306 imap_flags_store_process(get_imap_session(session),
307 get_data(session)->imap_flags_store);
308
309 r = mailimap_logout(get_imap_session(session));
310
311 return imap_error_to_mail_error(r);
312}
313
314static int imapdriver_noop(mailsession * session)
315{
316 int r;
317
318 r = mailimap_noop(get_imap_session(session));
319
320 return imap_error_to_mail_error(r);
321}
322
323static int imapdriver_build_folder_name(mailsession * session, char * mb,
324 char * name, char ** result)
325{
326 char delimiter[2] = "X";
327 char * folder_name;
328 mailimap * imap;
329 struct mailimap_mailbox_list * mb_list;
330 int r;
331 clist * imap_list;
332
333 imap = get_imap_session(session);
334
335 r = mailimap_list(imap, mb, "", &imap_list);
336 if (r != MAILIMAP_NO_ERROR)
337 return r;
338
339 if (clist_begin(imap_list) == NULL)
340 return MAIL_ERROR_LIST;
341
342 mb_list = clist_begin(imap_list)->data;
343 delimiter[0] = mb_list->mb_delimiter;
344
345 folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1);
346 if (folder_name == NULL)
347 return MAIL_ERROR_MEMORY;
348
349 strcpy(folder_name, mb);
350 strcat(folder_name, delimiter);
351 strcat(folder_name, name);
352
353 * result = folder_name;
354
355 return MAIL_NO_ERROR;
356}
357
358/* folders operations */
359
360static int imapdriver_create_folder(mailsession * session, char * mb)
361{
362 int r;
363
364 r = mailimap_create(get_imap_session(session), mb);
365
366 return imap_error_to_mail_error(r);
367}
368
369static int imapdriver_delete_folder(mailsession * session, char * mb)
370{
371 int r;
372
373 r = mailimap_delete(get_imap_session(session), mb);
374
375 return imap_error_to_mail_error(r);
376}
377
378static int imapdriver_rename_folder(mailsession * session, char * mb,
379 char * new_name)
380{
381 int r;
382
383 r = mailimap_rename(get_imap_session(session), mb, new_name);
384
385 return imap_error_to_mail_error(r);
386}
387
388static int imapdriver_check_folder(mailsession * session)
389{
390 int r;
391
392 imap_flags_store_process(get_imap_session(session),
393 get_data(session)->imap_flags_store);
394
395 r = mailimap_check(get_imap_session(session));
396
397 return imap_error_to_mail_error(r);
398}
399
400static int imapdriver_examine_folder(mailsession * session, char * mb)
401{
402 int r;
403
404 r = mailimap_examine(get_imap_session(session), mb);
405
406 return imap_error_to_mail_error(r);
407}
408
409static int imapdriver_select_folder(mailsession * session, char * mb)
410{
411 int r;
412 char * new_mb;
413 char * old_mb;
414
415 old_mb = get_data(session)->imap_mailbox;
416 if (old_mb != NULL)
417 if (strcmp(mb, old_mb) == 0)
418 return MAIL_NO_ERROR;
419
420 imap_flags_store_process(get_imap_session(session),
421 get_data(session)->imap_flags_store);
422
423 r = mailimap_select(get_imap_session(session), mb);
424
425 switch (r) {
426 case MAILIMAP_NO_ERROR:
427 new_mb = strdup(mb);
428 if (new_mb == NULL) {
429 if (old_mb != NULL)
430 free(old_mb);
431 get_data(session)->imap_mailbox = NULL;
432 return MAIL_ERROR_MEMORY;
433 }
434
435 get_data(session)->imap_mailbox = new_mb;
436
437 return MAIL_NO_ERROR;
438 default:
439 return imap_error_to_mail_error(r);
440 }
441}
442
443static int imapdriver_expunge_folder(mailsession * session)
444{
445 int r;
446
447 imap_flags_store_process(get_imap_session(session),
448 get_data(session)->imap_flags_store);
449
450 r = mailimap_expunge(get_imap_session(session));
451
452 return imap_error_to_mail_error(r);
453}
454
455static int status_selected_folder(mailsession * session, char * mb,
456 uint32_t * result_messages, uint32_t * result_recent,
457 uint32_t * result_unseen)
458{
459 int r;
460 int res;
461 mailimap * imap;
462 uint32_t exists;
463 uint32_t unseen;
464 uint32_t recent;
465 struct mailimap_search_key * search_key;
466 clist * search_result;
467
468 imap = get_imap_session(session);
469
470 exists = imap->imap_selection_info->sel_exists;
471 recent = imap->imap_selection_info->sel_recent;
472
473 search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
474 NULL, NULL, NULL, NULL, NULL,
475 NULL, NULL, NULL, NULL, NULL,
476 NULL, NULL, NULL, NULL, 0,
477 NULL, NULL, NULL, NULL, NULL,
478 NULL, 0, NULL, NULL, NULL);
479 if (search_key == NULL) {
480 res = MAIL_ERROR_MEMORY;
481 goto err;
482 }
483
484 /* default : use the RECENT count if search fails */
485 unseen = recent;
486 r = mailimap_search(imap, NULL, search_key, &search_result);
487 mailimap_search_key_free(search_key);
488 if (r == MAILIMAP_NO_ERROR) {
489 /* if this succeed, we use the real count */
490 unseen = clist_count(search_result);
491 mailimap_mailbox_data_search_free(search_result);
492 }
493
494 * result_messages = exists;
495 * result_unseen = unseen;
496 * result_recent = recent;
497
498 return MAIL_NO_ERROR;
499
500 err:
501 return res;
502}
503
504static int status_unselected_folder(mailsession * session, char * mb,
505 uint32_t * result_messages, uint32_t * result_recent,
506 uint32_t * result_unseen)
507{
508 struct mailimap_status_att_list * att_list;
509 struct mailimap_mailbox_data_status * status;
510 int r;
511 int res;
512 clistiter * cur;
513 mailimap * imap;
514
515 imap = get_imap_session(session);
516
517 att_list = mailimap_status_att_list_new_empty();
518 if (att_list == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
524 switch (r) {
525 case MAILIMAP_NO_ERROR:
526 break;
527 default:
528 res = MAIL_ERROR_MEMORY;
529 goto free;
530 }
531
532 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
533 switch (r) {
534 case MAILIMAP_NO_ERROR:
535 break;
536 default:
537 res = MAIL_ERROR_MEMORY;
538 goto free;
539 }
540
541 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
542 switch (r) {
543 case MAILIMAP_NO_ERROR:
544 break;
545 default:
546 res = MAIL_ERROR_MEMORY;
547 goto free;
548 }
549
550 r = mailimap_status(imap, mb, att_list, &status);
551
552 switch (r) {
553 case MAILIMAP_NO_ERROR:
554 break;
555 default:
556 res = imap_error_to_mail_error(r);
557 goto free;
558 }
559
560 * result_messages = 0;
561 * result_recent = 0;
562 * result_unseen = 0;
563
564 for (cur = clist_begin(status->st_info_list);
565 cur != NULL ; cur = clist_next(cur)) {
566 struct mailimap_status_info * status_info;
567
568 status_info = clist_content(cur);
569 switch (status_info->st_att) {
570 case MAILIMAP_STATUS_ATT_MESSAGES:
571 * result_messages = status_info->st_value;
572 break;
573 case MAILIMAP_STATUS_ATT_RECENT:
574 * result_recent = status_info->st_value;
575 break;
576 case MAILIMAP_STATUS_ATT_UNSEEN:
577 * result_unseen = status_info->st_value;
578 break;
579 }
580 }
581
582 mailimap_mailbox_data_status_free(status);
583 mailimap_status_att_list_free(att_list);
584
585 return MAIL_NO_ERROR;
586
587 free:
588 mailimap_status_att_list_free(att_list);
589 err:
590 return res;
591}
592
593static int imapdriver_status_folder(mailsession * session, char * mb,
594 uint32_t * result_messages, uint32_t * result_recent,
595 uint32_t * result_unseen)
596{
597 int res;
598 int current_folder;
599 char * current_mb;
600
601 if (mb == NULL) {
602 mb = get_data(session)->imap_mailbox;
603 if (mb == NULL) {
604 res = MAIL_ERROR_BAD_STATE;
605 goto err;
606 }
607 }
608
609 current_mb = get_data(session)->imap_mailbox;
610 if (strcmp(mb, current_mb) == 0)
611 current_folder = 1;
612 else
613 current_folder = 0;
614
615 if (current_folder)
616 return status_selected_folder(session, mb, result_messages,
617 result_recent, result_unseen);
618 else
619 return status_unselected_folder(session, mb, result_messages,
620 result_recent, result_unseen);
621
622 err:
623 return res;
624}
625
626/* TODO : more efficient functions */
627
628static int imapdriver_messages_number(mailsession * session, char * mb,
629 uint32_t * result)
630{
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 int r;
635
636 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
637 if (r != MAIL_NO_ERROR)
638 return r;
639
640 * result = messages;
641
642 return MAIL_NO_ERROR;
643}
644
645static int imapdriver_recent_number(mailsession * session, char * mb,
646 uint32_t * result)
647{
648 uint32_t messages;
649 uint32_t recent;
650 uint32_t unseen;
651 int r;
652
653 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
654 if (r != MAIL_NO_ERROR)
655 return r;
656
657 * result = recent;
658
659 return MAIL_NO_ERROR;
660}
661
662static int imapdriver_unseen_number(mailsession * session, char * mb,
663 uint32_t * result)
664{
665 uint32_t messages;
666 uint32_t recent;
667 uint32_t unseen;
668 int r;
669
670 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
671 if (r != MAIL_NO_ERROR)
672 return r;
673
674 * result = unseen;
675
676 return MAIL_NO_ERROR;
677}
678
679enum {
680 IMAP_LIST, IMAP_LSUB
681};
682
683static int imapdriver_list_lsub_folders(mailsession * session, int type,
684 char * mb,
685 struct mail_list ** result)
686{
687 clist * imap_list;
688 struct mail_list * resp;
689 int r;
690 int res;
691
692 switch (type) {
693 case IMAP_LIST:
694 r = mailimap_list(get_imap_session(session), mb,
695 "*", &imap_list);
696 break;
697 case IMAP_LSUB:
698 r = mailimap_lsub(get_imap_session(session), mb,
699 "*", &imap_list);
700 break;
701 default:
702 res = MAIL_ERROR_LIST;
703 goto err;
704 }
705
706 switch (r) {
707 case MAILIMAP_NO_ERROR:
708 break;
709 default:
710 res = imap_error_to_mail_error(r);
711 goto err;
712 }
713
714 r = imap_list_to_list(imap_list, &resp);
715 if (r != MAIL_NO_ERROR) {
716 mailimap_list_result_free(imap_list);
717 res = r;
718 goto err;
719 }
720
721 mailimap_list_result_free(imap_list);
722
723 * result = resp;
724
725 return MAIL_NO_ERROR;
726
727 err:
728 return res;
729}
730
731static int imapdriver_list_folders(mailsession * session, char * mb,
732 struct mail_list ** result)
733{
734 return imapdriver_list_lsub_folders(session, IMAP_LIST, mb,
735 result);
736}
737
738static int imapdriver_lsub_folders(mailsession * session, char * mb,
739 struct mail_list ** result)
740{
741 return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb,
742 result);
743}
744
745static int imapdriver_subscribe_folder(mailsession * session, char * mb)
746{
747 int r;
748
749 r = mailimap_subscribe(get_imap_session(session), mb);
750
751 return imap_error_to_mail_error(r);
752}
753
754static int imapdriver_unsubscribe_folder(mailsession * session, char * mb)
755{
756 int r;
757
758 r = mailimap_unsubscribe(get_imap_session(session), mb);
759
760 return imap_error_to_mail_error(r);
761}
762
763/* messages operations */
764
765static int imapdriver_append_message(mailsession * session,
766 char * message, size_t size)
767{
768 int r;
769
770 r = mailimap_append_simple(get_imap_session(session),
771 get_data(session)->imap_mailbox,
772 message, size);
773
774 return imap_error_to_mail_error(r);
775}
776
777static int imapdriver_append_message_flags(mailsession * session,
778 char * message, size_t size, struct mail_flags * flags)
779{
780 struct mailimap_flag_list * flag_list;
781 int r;
782
783 if (flags != NULL) {
784 r = imap_flags_to_imap_flags(flags, &flag_list);
785 if (r != MAIL_NO_ERROR)
786 return r;
787 }
788 else {
789 flag_list = NULL;
790 }
791
792 r = mailimap_append(get_imap_session(session),
793 get_data(session)->imap_mailbox,
794 flag_list, NULL, message, size);
795
796 if (flag_list != NULL)
797 mailimap_flag_list_free(flag_list);
798
799 return imap_error_to_mail_error(r);
800}
801
802static int imapdriver_copy_message(mailsession * session,
803 uint32_t num, char * mb)
804{
805 int r;
806 struct mailimap_set * set;
807 int res;
808
809 set = mailimap_set_new_single(num);
810 if (set == NULL) {
811 res = MAIL_ERROR_MEMORY;
812 goto err;
813 }
814
815 r = mailimap_uid_copy(get_imap_session(session), set, mb);
816
817 mailimap_set_free(set);
818
819 return imap_error_to_mail_error(r);
820
821 err:
822 return res;
823}
824
825static int imapdriver_get_messages_list(mailsession * session,
826 struct mailmessage_list ** result)
827{
828 return imap_get_messages_list(get_imap_session(session),
829 session, imap_message_driver, 1,
830 result);
831}
832
833
834
835#define IMAP_SET_MAX_COUNT 100
836
837static int
838imapdriver_get_envelopes_list(mailsession * session,
839 struct mailmessage_list * env_list)
840{
841 struct mailimap_set * set;
842 struct mailimap_fetch_att * fetch_att;
843 struct mailimap_fetch_type * fetch_type;
844 int res;
845 clist * fetch_result;
846 int r;
847 uint32_t exists;
848 clist * msg_list;
849 clistiter * set_iter;
850
851 if (get_imap_session(session)->imap_selection_info == NULL) {
852 res = MAIL_ERROR_BAD_STATE;
853 goto err;
854 }
855
856 imap_flags_store_process(get_imap_session(session),
857 get_data(session)->imap_flags_store);
858
859 exists = get_imap_session(session)->imap_selection_info->sel_exists;
860
861 if (exists == 0)
862 return MAIL_NO_ERROR;
863
864 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
865 if (fetch_type == NULL) {
866 res = MAIL_ERROR_MEMORY;
867 goto err;
868 }
869
870 fetch_att = mailimap_fetch_att_new_uid();
871 if (fetch_att == NULL) {
872 res = MAIL_ERROR_MEMORY;
873 goto free_fetch_type;
874 }
875
876 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
877 if (r != MAILIMAP_NO_ERROR) {
878 mailimap_fetch_att_free(fetch_att);
879 res = MAIL_ERROR_MEMORY;
880 goto free_fetch_type;
881 }
882
883 fetch_att = mailimap_fetch_att_new_flags();
884 if (fetch_att == NULL) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_fetch_type;
887 }
888
889 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
890 if (r != MAILIMAP_NO_ERROR) {
891 mailimap_fetch_att_free(fetch_att);
892 res = MAIL_ERROR_MEMORY;
893 goto free_fetch_type;
894 }
895
896 r = imap_add_envelope_fetch_att(fetch_type);
897 if (r != MAIL_NO_ERROR) {
898 res = r;
899 goto free_fetch_type;
900 }
901
902 r = maildriver_env_list_to_msg_list(env_list, &msg_list);
903 if (r != MAIL_NO_ERROR) {
904 res = MAIL_ERROR_MEMORY;
905 goto free_fetch_type;
906 }
907
908 if (clist_begin(msg_list) == NULL) {
909 /* no need to fetch envelopes */
910
911 mailimap_fetch_type_free(fetch_type);
912 clist_free(msg_list);
913 return MAIL_NO_ERROR;
914 }
915
916 r = msg_list_to_imap_set(msg_list, &set);
917 if (r != MAIL_NO_ERROR) {
918 clist_foreach(msg_list, (clist_func) free, NULL);
919 clist_free(msg_list);
920 res = MAIL_ERROR_MEMORY;
921 goto free_fetch_type;
922 }
923 clist_foreach(msg_list, (clist_func) free, NULL);
924 clist_free(msg_list);
925
926 set_iter = clist_begin(set->set_list);
927 while (set_iter != NULL) {
928 struct mailimap_set * subset;
929 unsigned int count;
930
931 subset = mailimap_set_new_empty();
932 if (subset == NULL) {
933 res = MAIL_ERROR_MEMORY;
934 mailimap_fetch_type_free(fetch_type);
935 mailimap_set_free(set);
936 res = MAIL_ERROR_MEMORY;
937 goto err;
938 }
939
940 count = 0;
941 while (count < IMAP_SET_MAX_COUNT) {
942 struct mailimap_set_item * item;
943
944 item = clist_content(set_iter);
945 set_iter = clist_delete(set->set_list, set_iter);
946
947 r = mailimap_set_add(subset, item);
948 if (r != MAILIMAP_NO_ERROR) {
949 mailimap_set_item_free(item);
950 mailimap_set_free(subset);
951 mailimap_fetch_type_free(fetch_type);
952 mailimap_set_free(set);
953 res = MAIL_ERROR_MEMORY;
954 goto err;
955 }
956
957 count ++;
958
959 if (set_iter == NULL)
960 break;
961 }
962
963 r = mailimap_uid_fetch(get_imap_session(session), subset,
964 fetch_type, &fetch_result);
965
966 mailimap_set_free(subset);
967
968 switch (r) {
969 case MAILIMAP_NO_ERROR:
970 break;
971 default:
972 mailimap_fetch_type_free(fetch_type);
973 mailimap_set_free(set);
974 return imap_error_to_mail_error(r);
975 }
976
977 if (clist_begin(fetch_result) == NULL) {
978 res = MAIL_ERROR_FETCH;
979 goto err;
980 }
981
982 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
983 mailimap_fetch_list_free(fetch_result);
984
985 if (r != MAIL_NO_ERROR) {
986 mailimap_fetch_type_free(fetch_type);
987 mailimap_set_free(set);
988 res = MAIL_ERROR_MEMORY;
989 goto err;
990 }
991 }
992
993#if 0
994 r = mailimap_uid_fetch(get_imap_session(session), set,
995 fetch_type, &fetch_result);
996#endif
997
998 mailimap_fetch_type_free(fetch_type);
999 mailimap_set_free(set);
1000#if 0
1001 switch (r) {
1002 case MAILIMAP_NO_ERROR:
1003 break;
1004 default:
1005 return imap_error_to_mail_error(r);
1006 }
1007
1008 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1009 mailimap_fetch_list_free(fetch_result);
1010
1011 if (r != MAIL_NO_ERROR) {
1012 res = MAIL_ERROR_MEMORY;
1013 goto err;
1014 }
1015#endif
1016
1017 return MAIL_NO_ERROR;
1018
1019 free_fetch_type:
1020 mailimap_fetch_type_free(fetch_type);
1021 err:
1022 return res;
1023}
1024
1025
1026#if 0
1027static int imapdriver_search_messages(mailsession * session, char * charset,
1028 struct mail_search_key * key,
1029 struct mail_search_result ** result)
1030{
1031 struct mailimap_search_key * imap_key;
1032 int r;
1033 clist * imap_result;
1034 clist * result_list;
1035 struct mail_search_result * search_result;
1036 clistiter * cur;
1037
1038 r = mail_search_to_imap_search(key, &imap_key);
1039 if (r != MAIL_NO_ERROR)
1040 return MAIL_ERROR_MEMORY;
1041
1042 r = mailimap_uid_search(get_imap_session(session), charset, imap_key,
1043 &imap_result);
1044
1045 mailimap_search_key_free(imap_key);
1046
1047 switch (r) {
1048 case MAILIMAP_NO_ERROR:
1049 break;
1050 default:
1051 return imap_error_to_mail_error(r);
1052 }
1053
1054 result_list = clist_new();
1055 if (result_list == NULL)
1056 return MAIL_ERROR_MEMORY;
1057
1058 for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) {
1059 uint32_t val = * (uint32_t *) clist_content(cur);
1060 uint32_t * new;
1061
1062 new = malloc(sizeof(* new));
1063 if (new == NULL) {
1064 goto free_imap_result;
1065 }
1066
1067 * new = val;
1068
1069 r = clist_append(result_list, new);
1070 if (r != 0) {
1071 free(new);
1072 goto free_imap_result;
1073 }
1074 }
1075
1076 search_result = mail_search_result_new(result_list);
1077 if (search_result == NULL)
1078 goto free_imap_result;
1079
1080 mailimap_search_result_free(imap_result);
1081
1082 * result = search_result;
1083
1084 return MAIL_NO_ERROR;
1085
1086 free_imap_result:
1087 mailimap_search_result_free(imap_result);
1088 return MAIL_ERROR_MEMORY;
1089}
1090#endif
1091
1092static int imapdriver_starttls(mailsession * session)
1093{
1094 mailimap * imap;
1095 int r;
1096 struct mailimap_capability_data * cap_data;
1097 clistiter * cur;
1098 int starttls;
1099 int fd;
1100 mailstream_low * low;
1101 mailstream_low * new_low;
1102 int capability_available;
1103
1104 imap = get_imap_session(session);
1105
1106 capability_available = FALSE;
1107 if (imap->imap_connection_info != NULL)
1108 if (imap->imap_connection_info->imap_capability != NULL) {
1109 capability_available = TRUE;
1110 cap_data = imap->imap_connection_info->imap_capability;
1111 }
1112
1113 if (!capability_available) {
1114 r = mailimap_capability(imap, &cap_data);
1115 switch (r) {
1116 case MAILIMAP_NO_ERROR:
1117 break;
1118 default:
1119 return imap_error_to_mail_error(r);
1120 }
1121 }
1122
1123 starttls = FALSE;
1124 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ;
1125 cur = clist_next(cur)) {
1126 struct mailimap_capability * cap;
1127
1128 cap = clist_content(cur);
1129
1130 if (cap->cap_type == MAILIMAP_CAPABILITY_NAME)
1131 if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
1132 starttls = TRUE;
1133 break;
1134 }
1135 }
1136
1137 if (!capability_available)
1138 mailimap_capability_data_free(cap_data);
1139
1140 if (!starttls)
1141 return MAIL_ERROR_NO_TLS;
1142
1143 r = mailimap_starttls(imap);
1144
1145 switch (r) {
1146 case MAILIMAP_NO_ERROR:
1147 break;
1148 default:
1149 return imap_error_to_mail_error(r);
1150 }
1151
1152 low = mailstream_get_low(imap->imap_stream);
1153 fd = mailstream_low_get_fd(low);
1154 if (fd == -1)
1155 return MAIL_ERROR_STREAM;
1156
1157 new_low = mailstream_low_ssl_open(fd);
1158 if (new_low == NULL)
1159 return MAIL_ERROR_STREAM;
1160
1161 mailstream_low_free(low);
1162 mailstream_set_low(imap->imap_stream, new_low);
1163
1164 return MAIL_NO_ERROR;
1165}
1166
1167static int imapdriver_get_message(mailsession * session,
1168 uint32_t num, mailmessage ** result)
1169{
1170 mailmessage * msg_info;
1171 int r;
1172
1173 msg_info = mailmessage_new();
1174 if (msg_info == NULL)
1175 return MAIL_ERROR_MEMORY;
1176
1177 r = mailmessage_init(msg_info, session, imap_message_driver, num, 0);
1178 if (r != MAIL_NO_ERROR) {
1179 mailmessage_free(msg_info);
1180 return r;
1181 }
1182
1183 * result = msg_info;
1184
1185 return MAIL_NO_ERROR;
1186}
1187
1188/* Retrieve a message by UID
1189
1190 libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1191 where UIDVALIDITY and UID are decimal representation of
1192 respectively uidvalidity and uid numbers.
1193
1194 Return value:
1195 MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1196 MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1197 MAIL_NO_ERROR if message was found. Result is in result
1198*/
1199
1200static int imapdriver_get_message_by_uid(mailsession * session,
1201 const char * uid,
1202 mailmessage ** result)
1203{
1204 uint32_t uidvalidity;
1205 uint32_t num;
1206 char * p1, * p2;
1207 mailimap * imap;
1208
1209 if (uid == NULL)
1210 return MAIL_ERROR_INVAL;
1211
1212 uidvalidity = strtoul(uid, &p1, 10);
1213 if (p1 == uid || * p1 != '-')
1214 return MAIL_ERROR_INVAL;
1215
1216 p1++;
1217 num = strtoul(p1, &p2, 10);
1218 if (p2 == p1 || * p2 != '\0')
1219 return MAIL_ERROR_INVAL;
1220
1221 imap = get_imap_session(session);
1222 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1223 return MAIL_ERROR_MSG_NOT_FOUND;
1224
1225 return imapdriver_get_message(session, num, result);
1226}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.h b/libetpan/src/driver/implementation/imap/imapdriver.h
new file mode 100644
index 0000000..cbc0c51
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_H
37
38#define IMAPDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46extern mailsession_driver * imap_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.c b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
new file mode 100644
index 0000000..806b282
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
@@ -0,0 +1,1370 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <string.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "imapdriver_tools.h"
50#include "mail_cache_db.h"
51#include "mailmessage.h"
52#include "imapdriver_cached_message.h"
53#include "maildriver.h"
54#include "imapdriver_types.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "maildriver_tools.h"
58#include "imapdriver.h"
59
60static int imapdriver_cached_initialize(mailsession * session);
61static void imapdriver_cached_uninitialize(mailsession * session);
62
63static int imapdriver_cached_parameters(mailsession * session,
64 int id, void * value);
65
66static int imapdriver_cached_connect_stream(mailsession * session,
67 mailstream * s);
68
69static int imapdriver_cached_starttls(mailsession * session);
70
71static int imapdriver_cached_login(mailsession * session,
72 char * userid, char * password);
73static int imapdriver_cached_logout(mailsession * session);
74static int imapdriver_cached_noop(mailsession * session);
75static int imapdriver_cached_build_folder_name(mailsession * session,
76 char * mb,
77 char * name, char ** result);
78static int imapdriver_cached_create_folder(mailsession * session, char * mb);
79static int imapdriver_cached_delete_folder(mailsession * session, char * mb);
80static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
81 char * new_name);
82static int imapdriver_cached_check_folder(mailsession * session);
83static int imapdriver_cached_examine_folder(mailsession * session,
84 char * mb);
85static int imapdriver_cached_select_folder(mailsession * session, char * mb);
86static int imapdriver_cached_expunge_folder(mailsession * session);
87static int imapdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages,
89 uint32_t * result_recent,
90 uint32_t * result_unseen);
91static int imapdriver_cached_messages_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94static int imapdriver_cached_recent_number(mailsession * session, char * mb,
95 uint32_t * result);
96static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
97 uint32_t * result);
98static int imapdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
101 struct mail_list ** result);
102static int imapdriver_cached_subscribe_folder(mailsession * session,
103 char * mb);
104static int imapdriver_cached_unsubscribe_folder(mailsession * session,
105 char * mb);
106static int imapdriver_cached_append_message(mailsession * session,
107 char * message, size_t size);
108static int imapdriver_cached_append_message_flags(mailsession * session,
109 char * message, size_t size, struct mail_flags * flags);
110static int imapdriver_cached_copy_message(mailsession * session,
111 uint32_t num, char * mb);
112
113static int imapdriver_cached_get_messages_list(mailsession * session,
114 struct mailmessage_list **
115 result);
116static int
117imapdriver_cached_get_envelopes_list(mailsession * session,
118 struct mailmessage_list * env_list);
119static int imapdriver_cached_remove_message(mailsession * session,
120 uint32_t num);
121
122#if 0
123static int imapdriver_cached_search_messages(mailsession * session,
124 char * charset,
125 struct mail_search_key * key,
126 struct mail_search_result **
127 result);
128#endif
129
130static int imapdriver_cached_get_message(mailsession * session,
131 uint32_t num, mailmessage ** result);
132
133static int imapdriver_cached_get_message_by_uid(mailsession * session,
134 const char * uid,
135 mailmessage ** result);
136
137static mailsession_driver local_imap_cached_session_driver = {
138 .sess_name = "imap-cached",
139
140 .sess_initialize = imapdriver_cached_initialize,
141 .sess_uninitialize = imapdriver_cached_uninitialize,
142
143 .sess_parameters = imapdriver_cached_parameters,
144
145 .sess_connect_stream = imapdriver_cached_connect_stream,
146 .sess_connect_path = NULL,
147 .sess_starttls = imapdriver_cached_starttls,
148 .sess_login = imapdriver_cached_login,
149 .sess_logout = imapdriver_cached_logout,
150 .sess_noop = imapdriver_cached_noop,
151
152 .sess_build_folder_name = imapdriver_cached_build_folder_name,
153 .sess_create_folder = imapdriver_cached_create_folder,
154 .sess_delete_folder = imapdriver_cached_delete_folder,
155 .sess_rename_folder = imapdriver_cached_rename_folder,
156 .sess_check_folder = imapdriver_cached_check_folder,
157 .sess_examine_folder = imapdriver_cached_examine_folder,
158 .sess_select_folder = imapdriver_cached_select_folder,
159 .sess_expunge_folder = imapdriver_cached_expunge_folder,
160 .sess_status_folder = imapdriver_cached_status_folder,
161 .sess_messages_number = imapdriver_cached_messages_number,
162 .sess_recent_number = imapdriver_cached_recent_number,
163 .sess_unseen_number = imapdriver_cached_unseen_number,
164 .sess_list_folders = imapdriver_cached_list_folders,
165 .sess_lsub_folders = imapdriver_cached_lsub_folders,
166 .sess_subscribe_folder = imapdriver_cached_subscribe_folder,
167 .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder,
168
169 .sess_append_message = imapdriver_cached_append_message,
170 .sess_append_message_flags = imapdriver_cached_append_message_flags,
171 .sess_copy_message = imapdriver_cached_copy_message,
172 .sess_move_message = NULL,
173
174 .sess_get_messages_list = imapdriver_cached_get_messages_list,
175 .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list,
176 .sess_remove_message = imapdriver_cached_remove_message,
177#if 0
178 .sess_search_messages = imapdriver_cached_search_messages,
179#endif
180
181 .sess_get_message = imapdriver_cached_get_message,
182 .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid,
183};
184
185mailsession_driver * imap_cached_session_driver =
186&local_imap_cached_session_driver;
187
188#define CACHE_MESSAGE_LIST
189
190static inline struct imap_cached_session_state_data *
191get_cached_data(mailsession * session)
192{
193 return session->sess_data;
194}
195
196static inline mailsession * get_ancestor(mailsession * s)
197{
198 return get_cached_data(s)->imap_ancestor;
199}
200
201static inline
202struct imap_session_state_data * get_ancestor_data(mailsession * s)
203{
204 return get_ancestor(s)->sess_data;
205}
206
207static inline mailimap * get_imap_session(mailsession * session)
208{
209 return get_ancestor_data(session)->imap_session;
210}
211
212static int imapdriver_cached_initialize(mailsession * session)
213{
214 struct imap_cached_session_state_data * data;
215
216 data = malloc(sizeof(* data));
217 if (data == NULL)
218 goto err;
219
220 data->imap_ancestor = mailsession_new(imap_session_driver);
221 if (data->imap_ancestor == NULL)
222 goto free_data;
223 data->imap_quoted_mb = NULL;
224 data->imap_cache_directory[0] = '\0';
225 data->imap_uid_list = carray_new(128);
226 if (data->imap_uid_list == NULL)
227 goto free_session;
228
229 session->sess_data = data;
230
231 return MAIL_NO_ERROR;
232
233 free_session:
234 mailsession_free(data->imap_ancestor);
235 free_data:
236 free(data);
237 err:
238 return MAIL_ERROR_MEMORY;
239}
240
241static void
242free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data)
243{
244 if (imap_cached_data->imap_quoted_mb != NULL) {
245 free(imap_cached_data->imap_quoted_mb);
246 imap_cached_data->imap_quoted_mb = NULL;
247 }
248}
249
250struct uid_cache_item {
251 uint32_t uid;
252 uint32_t size;
253};
254
255static int update_uid_cache(mailsession * session,
256 struct mailmessage_list * env_list)
257{
258 unsigned int i;
259 int r;
260 struct imap_cached_session_state_data * data;
261 int res;
262
263 data = get_cached_data(session);
264
265 /* free all UID cache */
266 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
267 struct uid_cache_item * cache_item;
268
269 cache_item = carray_get(data->imap_uid_list, i);
270 free(cache_item);
271 }
272
273 /* build UID cache */
274 r = carray_set_size(data->imap_uid_list,
275 carray_count(env_list->msg_tab));
276 if (r < 0) {
277 res = MAIL_ERROR_MEMORY;
278 goto err;
279 }
280
281 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
282 struct uid_cache_item * cache_item;
283 mailmessage * msg;
284
285 cache_item = malloc(sizeof(* cache_item));
286 if (cache_item == NULL) {
287 res = MAIL_ERROR_MEMORY;
288 goto err;
289 }
290 msg = carray_get(env_list->msg_tab, i);
291 cache_item->uid = msg->msg_index;
292 cache_item->size = msg->msg_size;
293
294 carray_set(data->imap_uid_list, i, cache_item);
295 }
296
297 return MAIL_NO_ERROR;
298
299 err:
300 return res;
301}
302
303static void check_for_uid_cache(mailsession * session)
304{
305#if 0
306 mailsession * imap;
307#endif
308 mailimap * imap;
309#if 0
310 struct imap_session_state_data * imap_data;
311#endif
312 clist * list;
313 clistiter * cur;
314 struct imap_cached_session_state_data * data;
315 unsigned int i;
316 unsigned dest;
317
318 data = get_cached_data(session);
319#if 0
320 imap = get_ancestor(session);
321
322 imap_data = imap->data;
323#endif
324
325 imap = get_imap_session(session);
326
327 if (imap->imap_response_info == NULL)
328 return;
329
330 list = imap->imap_response_info->rsp_expunged;
331 if (list == NULL)
332 return;
333
334 dest = 0;
335 i = 0;
336 /* remove expunged */
337 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
338 uint32_t expunged;
339
340 expunged = * (uint32_t *) clist_content(cur);
341
342 while (i < carray_count(data->imap_uid_list)) {
343 struct uid_cache_item * cache_item;
344
345 if (dest + 1 == expunged) {
346 cache_item = carray_get(data->imap_uid_list, i);
347 free(cache_item);
348 i ++;
349 break;
350 }
351 else {
352 cache_item = carray_get(data->imap_uid_list, i);
353 carray_set(data->imap_uid_list, dest, cache_item);
354 i ++;
355 dest ++;
356 }
357 }
358 }
359 /* complete list */
360 while (i < carray_count(data->imap_uid_list)) {
361 struct uid_cache_item * cache_item;
362
363 cache_item = carray_get(data->imap_uid_list, i);
364 carray_set(data->imap_uid_list, dest, cache_item);
365 i ++;
366 dest ++;
367 }
368 carray_set_size(data->imap_uid_list, dest);
369}
370
371static void imapdriver_cached_uninitialize(mailsession * session)
372{
373 struct imap_cached_session_state_data * data;
374 unsigned int i;
375
376 data = get_cached_data(session);
377
378 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
379 struct uid_cache_item * cache_item;
380
381 cache_item = carray_get(data->imap_uid_list, i);
382 free(cache_item);
383 }
384 carray_free(data->imap_uid_list);
385 free_quoted_mb(data);
386 mailsession_free(data->imap_ancestor);
387 free(data);
388
389 session->sess_data = NULL;
390}
391
392
393static int imapdriver_cached_parameters(mailsession * session,
394 int id, void * value)
395{
396 struct imap_cached_session_state_data * data;
397 int r;
398
399 data = get_cached_data(session);
400
401 switch (id) {
402 case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY:
403 strncpy(data->imap_cache_directory, value, PATH_MAX);
404 data->imap_cache_directory[PATH_MAX - 1] = '\0';
405
406 r = generic_cache_create_dir(data->imap_cache_directory);
407 if (r != MAIL_NO_ERROR)
408 return r;
409
410 return MAIL_NO_ERROR;
411 }
412
413 return MAIL_ERROR_INVAL;
414}
415
416
417static int imapdriver_cached_connect_stream(mailsession * session,
418 mailstream * s)
419{
420 int r;
421
422 check_for_uid_cache(session);
423
424 r = mailsession_connect_stream(get_ancestor(session), s);
425
426 check_for_uid_cache(session);
427
428 return r;
429}
430
431static int imapdriver_cached_starttls(mailsession * session)
432{
433 int r;
434
435 r = mailsession_starttls(get_ancestor(session));
436
437 check_for_uid_cache(session);
438
439 return r;
440}
441
442static int imapdriver_cached_login(mailsession * session,
443 char * userid, char * password)
444{
445 int r;
446
447 r = mailsession_login(get_ancestor(session), userid, password);
448
449 check_for_uid_cache(session);
450
451 return r;
452}
453
454static int imapdriver_cached_logout(mailsession * session)
455{
456 int r;
457
458 r = mailsession_logout(get_ancestor(session));
459
460 check_for_uid_cache(session);
461
462 if (r == MAIL_NO_ERROR) {
463 struct imap_cached_session_state_data * imap_cached_data;
464
465 imap_cached_data = get_cached_data(session);
466
467 free_quoted_mb(imap_cached_data);
468 }
469
470 return r;
471}
472
473static int imapdriver_cached_noop(mailsession * session)
474{
475 int r;
476
477 r = mailsession_noop(get_ancestor(session));
478
479 check_for_uid_cache(session);
480
481 return r;
482}
483
484static int imapdriver_cached_build_folder_name(mailsession * session,
485 char * mb,
486 char * name, char ** result)
487{
488 int r;
489
490 r = mailsession_build_folder_name(get_ancestor(session), mb,
491 name, result);
492
493 check_for_uid_cache(session);
494
495 return r;
496}
497
498static int imapdriver_cached_create_folder(mailsession * session, char * mb)
499{
500 int r;
501
502 r = mailsession_create_folder(get_ancestor(session), mb);
503
504 check_for_uid_cache(session);
505
506 return r;
507}
508
509static int imapdriver_cached_delete_folder(mailsession * session, char * mb)
510{
511 int r;
512
513 r = mailsession_delete_folder(get_ancestor(session), mb);
514
515 check_for_uid_cache(session);
516
517 return r;
518}
519
520static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
521 char * new_name)
522{
523 int r;
524
525 r = mailsession_rename_folder(get_ancestor(session), mb, new_name);
526
527 check_for_uid_cache(session);
528
529 return r;
530}
531
532static int imapdriver_cached_check_folder(mailsession * session)
533{
534 int r;
535
536 r = mailsession_check_folder(get_ancestor(session));
537
538 check_for_uid_cache(session);
539
540 return r;
541}
542
543static int imapdriver_cached_examine_folder(mailsession * session,
544 char * mb)
545{
546 int r;
547
548 r = mailsession_examine_folder(get_ancestor(session), mb);
549
550 check_for_uid_cache(session);
551
552 return r;
553}
554
555static int get_cache_folder(mailsession * session, char ** result)
556{
557#if 0
558 mailsession * imap_session;
559#endif
560 mailimap * imap;
561 char * mb;
562 char * cache_dir;
563 char * dirname;
564 char * quoted_mb;
565 int res;
566 int r;
567 char key[PATH_MAX];
568#if 0
569 struct imap_session_state_data * imap_data;
570 struct imap_cached_session_state_data * cached_data;
571#endif
572
573#if 0
574 imap_session = get_ancestor(session);
575 imap_data = imap_session->data;
576 imap = imap_data->session;
577#endif
578 imap = get_imap_session(session);
579
580 mb = get_ancestor_data(session)->imap_mailbox;
581
582 cache_dir = get_cached_data(session)->imap_cache_directory;
583
584 if (imap->imap_state != MAILIMAP_STATE_SELECTED)
585 return MAIL_ERROR_BAD_STATE;
586
587 if (imap->imap_selection_info == NULL)
588 return MAIL_ERROR_BAD_STATE;
589
590 quoted_mb = maildriver_quote_mailbox(mb);
591 if (quoted_mb == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto err;
594 }
595
596 snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb);
597
598 dirname = strdup(key);
599 if (dirname == NULL) {
600 res = MAIL_ERROR_MEMORY;
601 goto free_mb;
602 }
603
604 r = generic_cache_create_dir(dirname);
605 if (r != MAIL_NO_ERROR) {
606 res = r;
607 goto free_dirname;
608 }
609
610 free(quoted_mb);
611
612 * result = dirname;
613
614 return MAIL_NO_ERROR;
615
616 free_dirname:
617 free(dirname);
618 free_mb:
619 free(quoted_mb);
620 err:
621 return res;
622}
623
624static int imapdriver_cached_select_folder(mailsession * session, char * mb)
625{
626 int r;
627 char * quoted_mb;
628 struct imap_cached_session_state_data * data;
629 mailsession * imap;
630 char * old_mb;
631
632 imap = get_ancestor(session);
633
634 old_mb = get_ancestor_data(session)->imap_mailbox;
635 if (old_mb != NULL)
636 if (strcmp(mb, old_mb) == 0)
637 return MAIL_NO_ERROR;
638
639 r = mailsession_select_folder(get_ancestor(session), mb);
640 if (r != MAIL_NO_ERROR)
641 return r;
642
643 check_for_uid_cache(session);
644
645 r = get_cache_folder(session, &quoted_mb);
646 if (r != MAIL_NO_ERROR)
647 return r;
648
649 data = get_cached_data(session);
650 if (data->imap_quoted_mb != NULL)
651 free(data->imap_quoted_mb);
652 data->imap_quoted_mb = quoted_mb;
653
654 /* clear UID cache */
655 carray_set_size(data->imap_uid_list, 0);
656
657 return MAIL_NO_ERROR;
658}
659
660static int imapdriver_cached_expunge_folder(mailsession * session)
661{
662 int r;
663
664 r = mailsession_expunge_folder(get_ancestor(session));
665
666 check_for_uid_cache(session);
667
668 return r;
669}
670
671static int imapdriver_cached_status_folder(mailsession * session, char * mb,
672 uint32_t * result_messages, uint32_t * result_recent,
673 uint32_t * result_unseen)
674{
675 int r;
676
677 r = mailsession_status_folder(get_ancestor(session), mb, result_messages,
678 result_recent, result_unseen);
679
680 check_for_uid_cache(session);
681
682 return r;
683}
684
685static int imapdriver_cached_messages_number(mailsession * session,
686 char * mb,
687 uint32_t * result)
688{
689 int r;
690
691 r = mailsession_messages_number(get_ancestor(session), mb, result);
692
693 check_for_uid_cache(session);
694
695 return r;
696}
697
698static int imapdriver_cached_recent_number(mailsession * session, char * mb,
699 uint32_t * result)
700{
701 int r;
702
703 r = mailsession_recent_number(get_ancestor(session), mb, result);
704
705 check_for_uid_cache(session);
706
707 return r;
708}
709
710static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
711 uint32_t * result)
712{
713 int r;
714
715 r = mailsession_unseen_number(get_ancestor(session), mb, result);
716
717 check_for_uid_cache(session);
718
719 return r;
720}
721
722static int imapdriver_cached_list_folders(mailsession * session, char * mb,
723 struct mail_list ** result)
724{
725 int r;
726
727 r = mailsession_list_folders(get_ancestor(session), mb, result);
728
729 check_for_uid_cache(session);
730
731 return r;
732}
733
734static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
735 struct mail_list ** result)
736{
737 int r;
738
739 r = mailsession_lsub_folders(get_ancestor(session), mb, result);
740
741 check_for_uid_cache(session);
742
743 return r;
744}
745
746static int imapdriver_cached_subscribe_folder(mailsession * session,
747 char * mb)
748{
749 int r;
750
751 r = mailsession_subscribe_folder(get_ancestor(session), mb);
752
753 check_for_uid_cache(session);
754
755 return r;
756}
757
758static int imapdriver_cached_unsubscribe_folder(mailsession * session,
759 char * mb)
760{
761 int r;
762
763 r = mailsession_unsubscribe_folder(get_ancestor(session), mb);
764
765 check_for_uid_cache(session);
766
767 return r;
768}
769
770static int imapdriver_cached_append_message(mailsession * session,
771 char * message, size_t size)
772{
773 int r;
774
775 r = mailsession_append_message(get_ancestor(session), message, size);
776
777 check_for_uid_cache(session);
778
779 return r;
780}
781
782static int imapdriver_cached_append_message_flags(mailsession * session,
783 char * message, size_t size, struct mail_flags * flags)
784{
785 int r;
786
787 r = mailsession_append_message_flags(get_ancestor(session),
788 message, size, flags);
789
790 check_for_uid_cache(session);
791
792 return r;
793}
794
795static int imapdriver_cached_copy_message(mailsession * session,
796 uint32_t num, char * mb)
797{
798 int r;
799
800 r = mailsession_copy_message(get_ancestor(session), num, mb);
801
802 check_for_uid_cache(session);
803
804 return r;
805}
806
807static int cmp_uid(uint32_t ** pa, uint32_t ** pb)
808{
809 uint32_t * a;
810 uint32_t * b;
811
812 a = * pa;
813 b = * pb;
814
815 return * a - * b;
816}
817
818
819static int imapdriver_cached_get_messages_list(mailsession * session,
820 struct mailmessage_list **
821 result)
822{
823#if 0
824 mailsession * imap_session;
825#endif
826 mailimap * imap;
827 uint32_t uid_max;
828 struct imap_cached_session_state_data * data;
829 struct mailmessage_list * env_list;
830 unsigned i;
831 int r;
832 int res;
833 carray * tab;
834
835#if 0
836 data = session->data;
837 imap_session = get_ancestor(session);
838 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
839#endif
840 data = get_cached_data(session);
841 imap = get_imap_session(session);
842
843 uid_max = 0;
844
845#ifdef CACHE_MESSAGE_LIST
846 /* get UID max */
847 uid_max = 0;
848 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
849 struct uid_cache_item * cache_item;
850
851 cache_item = carray_get(data->imap_uid_list, i);
852 if (cache_item->uid > uid_max)
853 uid_max = cache_item->uid;
854 }
855#endif
856
857 r = imap_get_messages_list(imap, session, imap_cached_message_driver,
858 uid_max + 1, &env_list);
859
860 check_for_uid_cache(session);
861
862 if (r != MAIL_NO_ERROR) {
863 res = r;
864 goto err;
865 }
866
867#ifdef CACHE_MESSAGE_LIST
868 /* remove unsollicited message */
869 i = 0;
870 while (i < carray_count(env_list->msg_tab)) {
871 mailmessage * msg;
872
873 msg = carray_get(env_list->msg_tab, i);
874 if (msg->msg_index < uid_max + 1) {
875 mailmessage * msg;
876
877 msg = carray_get(env_list->msg_tab, i);
878 mailmessage_free(msg);
879 carray_delete(env_list->msg_tab, i);
880 }
881 else {
882 i ++;
883 }
884 }
885
886 tab = carray_new(carray_count(env_list->msg_tab) +
887 carray_count(data->imap_uid_list));
888 if (tab == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto free;
891 }
892 carray_set_size(tab,
893 carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list));
894
895 /* sort cached data before adding them to the list */
896 qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list),
897 sizeof(* carray_data(data->imap_uid_list)),
898 (int (*)(const void *, const void *)) cmp_uid);
899
900 /* adds cached UID */
901 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
902 struct uid_cache_item * cache_item;
903 mailmessage * msg;
904
905 cache_item = carray_get(data->imap_uid_list, i);
906
907 msg = mailmessage_new();
908 if (msg == NULL) {
909 res = MAIL_ERROR_MEMORY;
910 goto free;
911 }
912
913 r = mailmessage_init(msg, session, imap_cached_message_driver,
914 cache_item->uid, cache_item->size);
915 if (r != MAIL_NO_ERROR) {
916 mailmessage_free(msg);
917 res = r;
918 goto free;
919 }
920
921 carray_set(tab, i, msg);
922 }
923
924 /* adds new elements */
925 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
926 mailmessage * msg;
927
928 msg = carray_get(env_list->msg_tab, i);
929 carray_set(tab, carray_count(data->imap_uid_list) + i, msg);
930 }
931
932 /* replace list of messages in env_list */
933 carray_free(env_list->msg_tab);
934 env_list->msg_tab = tab;
935
936 r = update_uid_cache(session, env_list);
937 if (r != MAIL_NO_ERROR) {
938 res = r;
939 goto free;
940 }
941#endif
942
943 * result = env_list;
944
945 return MAIL_NO_ERROR;
946
947 free:
948 mailmessage_list_free(env_list);
949 err:
950 return res;
951}
952
953#define IMAP_SET_MAX_COUNT 100
954
955static int get_flags_list(mailsession * session,
956 struct mailmessage_list * env_list)
957{
958 struct mailimap_set * set;
959 struct mailimap_fetch_att * fetch_att;
960 struct mailimap_fetch_type * fetch_type;
961 int res;
962 clist * fetch_result;
963 int r;
964 clist * msg_list;
965#if 0
966 struct imap_session_state_data * data;
967#endif
968 unsigned i;
969 unsigned dest;
970 clistiter * set_iter;
971
972#if 0
973 data = session->data;
974#endif
975
976 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
977 if (fetch_type == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto err;
980 }
981
982 fetch_att = mailimap_fetch_att_new_uid();
983 if (fetch_att == NULL) {
984 res = MAIL_ERROR_MEMORY;
985 goto free_fetch_type;
986 }
987
988 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
989 if (r != MAILIMAP_NO_ERROR) {
990 mailimap_fetch_att_free(fetch_att);
991 res = MAIL_ERROR_MEMORY;
992 goto free_fetch_type;
993 }
994
995 fetch_att = mailimap_fetch_att_new_flags();
996 if (fetch_att == NULL) {
997 res = MAIL_ERROR_MEMORY;
998 goto free_fetch_type;
999 }
1000
1001 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1002 if (r != MAILIMAP_NO_ERROR) {
1003 mailimap_fetch_att_free(fetch_att);
1004 res = MAIL_ERROR_MEMORY;
1005 goto free_fetch_type;
1006 }
1007
1008 r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list);
1009 if (r != MAIL_NO_ERROR) {
1010 res = MAIL_ERROR_MEMORY;
1011 goto free_fetch_type;
1012 }
1013
1014 if (clist_begin(msg_list) == NULL) {
1015 /* no need to fetch envelopes */
1016
1017 clist_free(msg_list);
1018 mailimap_fetch_type_free(fetch_type);
1019 return MAIL_NO_ERROR;
1020 }
1021
1022 r = msg_list_to_imap_set(msg_list, &set);
1023 if (r != MAIL_NO_ERROR) {
1024 clist_foreach(msg_list, (clist_func) free, NULL);
1025 clist_free(msg_list);
1026 res = MAIL_ERROR_MEMORY;
1027 goto free_fetch_type;
1028 }
1029 clist_foreach(msg_list, (clist_func) free, NULL);
1030 clist_free(msg_list);
1031
1032 set_iter = clist_begin(set->set_list);
1033 while (set_iter != NULL) {
1034 struct mailimap_set * subset;
1035 unsigned int count;
1036
1037 subset = mailimap_set_new_empty();
1038 if (subset == NULL) {
1039 res = MAIL_ERROR_MEMORY;
1040 mailimap_fetch_type_free(fetch_type);
1041 mailimap_set_free(set);
1042 res = MAIL_ERROR_MEMORY;
1043 goto err;
1044 }
1045
1046 count = 0;
1047 while (count < IMAP_SET_MAX_COUNT) {
1048 struct mailimap_set_item * item;
1049
1050 item = clist_content(set_iter);
1051 set_iter = clist_delete(set->set_list, set_iter);
1052
1053 r = mailimap_set_add(subset, item);
1054 if (r != MAILIMAP_NO_ERROR) {
1055 mailimap_set_item_free(item);
1056 mailimap_set_free(subset);
1057 mailimap_fetch_type_free(fetch_type);
1058 mailimap_set_free(set);
1059 res = MAIL_ERROR_MEMORY;
1060 goto err;
1061 }
1062
1063 count ++;
1064
1065 if (set_iter == NULL)
1066 break;
1067 }
1068
1069 r = mailimap_uid_fetch(get_imap_session(session), subset,
1070 fetch_type, &fetch_result);
1071
1072 mailimap_set_free(subset);
1073
1074 switch (r) {
1075 case MAILIMAP_NO_ERROR:
1076 break;
1077 default:
1078 mailimap_fetch_type_free(fetch_type);
1079 mailimap_set_free(set);
1080 return imap_error_to_mail_error(r);
1081 }
1082
1083 if (clist_begin(fetch_result) == NULL) {
1084 res = MAIL_ERROR_FETCH;
1085 goto err;
1086 }
1087
1088 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1089 mailimap_fetch_list_free(fetch_result);
1090
1091 if (r != MAIL_NO_ERROR) {
1092 mailimap_fetch_type_free(fetch_type);
1093 mailimap_set_free(set);
1094 res = MAIL_ERROR_MEMORY;
1095 goto err;
1096 }
1097 }
1098
1099#if 0
1100 r = mailimap_uid_fetch(get_imap_session(session), set,
1101 fetch_type, &fetch_result);
1102#endif
1103
1104 mailimap_fetch_type_free(fetch_type);
1105 mailimap_set_free(set);
1106
1107#if 0
1108 switch (r) {
1109 case MAILIMAP_NO_ERROR:
1110 break;
1111 default:
1112 return imap_error_to_mail_error(r);
1113 }
1114
1115 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1116 mailimap_fetch_list_free(fetch_result);
1117
1118 if (r != MAIL_NO_ERROR) {
1119 res = MAIL_ERROR_MEMORY;
1120 goto err;
1121 }
1122#endif
1123
1124 /* remove messages that don't have flags */
1125 i = 0;
1126 dest = 0;
1127 while (i < carray_count(env_list->msg_tab)) {
1128 mailmessage * msg;
1129
1130 msg = carray_get(env_list->msg_tab, i);
1131 if (msg->msg_flags != NULL) {
1132 carray_set(env_list->msg_tab, dest, msg);
1133 dest ++;
1134 }
1135 else {
1136 mailmessage_free(msg);
1137 }
1138 i ++;
1139 }
1140 carray_set_size(env_list->msg_tab, dest);
1141
1142 return MAIL_NO_ERROR;
1143
1144 free_fetch_type:
1145 mailimap_fetch_type_free(fetch_type);
1146 err:
1147 return res;
1148}
1149
1150
1151#define ENV_NAME "env.db"
1152
1153static void get_uid_from_filename(char * filename)
1154{
1155 char * p;
1156
1157 p = strstr(filename, "-part");
1158 if (p != NULL)
1159 * p = 0;
1160 p = strstr(filename, "-envelope");
1161 if (p != NULL)
1162 * p = 0;
1163 p = strstr(filename, "-rfc822");
1164 if (p != NULL)
1165 * p = 0;
1166}
1167
1168static int
1169imapdriver_cached_get_envelopes_list(mailsession * session,
1170 struct mailmessage_list * env_list)
1171{
1172 int r;
1173 int res;
1174 uint32_t i;
1175 struct imap_cached_session_state_data * data;
1176 MMAPString * mmapstr;
1177 struct mail_cache_db * cache_db;
1178 char filename[PATH_MAX];
1179
1180 data = get_cached_data(session);
1181 if (data->imap_quoted_mb == NULL) {
1182 res = MAIL_ERROR_BAD_STATE;
1183 goto err;
1184 }
1185
1186 mmapstr = mmap_string_new("");
1187 if (mmapstr == NULL) {
1188 res = MAIL_ERROR_MEMORY;
1189 goto err;
1190 }
1191
1192 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
1193
1194 r = mail_cache_db_open_lock(filename, &cache_db);
1195 if (r < 0) {
1196 res = MAIL_ERROR_MEMORY;
1197 goto free_mmapstr;
1198 }
1199
1200 /* fill with cached */
1201
1202 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1203 mailmessage * msg;
1204 struct mailimf_fields * fields;
1205
1206 msg = carray_get(env_list->msg_tab, i);
1207
1208 if (msg->msg_fields == NULL) {
1209 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
1210 session, msg, &fields);
1211 if (r == MAIL_NO_ERROR) {
1212 msg->msg_cached = TRUE;
1213 msg->msg_fields = fields;
1214 }
1215 }
1216 }
1217
1218 mail_cache_db_close_unlock(filename, cache_db);
1219
1220 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1221
1222 check_for_uid_cache(session);
1223
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mmapstr;
1227 }
1228
1229 r = get_flags_list(session, env_list);
1230
1231 if (r != MAIL_NO_ERROR) {
1232 res = r;
1233 goto free_mmapstr;
1234 }
1235
1236#ifdef CACHE_MESSAGE_LIST
1237 r = update_uid_cache(session, env_list);
1238 if (r != MAIL_NO_ERROR) {
1239 res = r;
1240 goto free_mmapstr;
1241 }
1242#endif
1243
1244 /* must write cache */
1245
1246 r = mail_cache_db_open_lock(filename, &cache_db);
1247 if (r < 0) {
1248 res = MAIL_ERROR_MEMORY;
1249 goto free_mmapstr;
1250 }
1251
1252 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1253 mailmessage * msg;
1254
1255 msg = carray_get(env_list->msg_tab, i);
1256
1257 if (msg->msg_fields != NULL) {
1258 if (!msg->msg_cached) {
1259 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
1260 session, msg, msg->msg_fields);
1261 }
1262 }
1263 }
1264
1265 /* flush cache */
1266
1267 maildriver_cache_clean_up(cache_db, NULL, env_list);
1268
1269 mail_cache_db_close_unlock(filename, cache_db);
1270 mmap_string_free(mmapstr);
1271
1272 /* remove cache files */
1273
1274 maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list,
1275 get_uid_from_filename);
1276
1277 return MAIL_NO_ERROR;
1278
1279 free_mmapstr:
1280 mmap_string_free(mmapstr);
1281 err:
1282 return res;
1283}
1284
1285static int imapdriver_cached_remove_message(mailsession * session,
1286 uint32_t num)
1287{
1288 int r;
1289
1290 r = mailsession_remove_message(get_ancestor(session), num);
1291
1292 check_for_uid_cache(session);
1293
1294 return r;
1295}
1296
1297#if 0
1298static int imapdriver_cached_search_messages(mailsession * session,
1299 char * charset,
1300 struct mail_search_key * key,
1301 struct mail_search_result **
1302 result)
1303{
1304 int r;
1305
1306 r = mailsession_search_messages(get_ancestor(session), charset, key, result);
1307
1308 check_for_uid_cache(session);
1309
1310 return r;
1311}
1312#endif
1313
1314static int imapdriver_cached_get_message(mailsession * session,
1315 uint32_t num, mailmessage ** result)
1316{
1317 mailmessage * msg_info;
1318 int r;
1319
1320 msg_info = mailmessage_new();
1321 if (msg_info == NULL)
1322 return MAIL_ERROR_MEMORY;
1323
1324 r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0);
1325 if (r != MAIL_NO_ERROR) {
1326 mailmessage_free(msg_info);
1327 return r;
1328 }
1329
1330 * result = msg_info;
1331
1332 return MAIL_NO_ERROR;
1333}
1334
1335/* Retrieve a message by UID
1336 * libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1337 * where UIDVALIDITY and UID are decimal representation of
1338 * respectively uidvalidity and uid numbers.
1339 * Return value:
1340 * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1341 * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1342 * MAIL_NO_ERROR if message was found. Result is in result
1343 */
1344static int imapdriver_cached_get_message_by_uid(mailsession * session,
1345 const char * uid,
1346 mailmessage ** result)
1347{
1348 uint32_t uidvalidity;
1349 uint32_t num;
1350 char * p1, * p2;
1351 mailimap *imap;
1352
1353 if (uid == NULL)
1354 return MAIL_ERROR_INVAL;
1355
1356 uidvalidity = strtoul(uid, &p1, 10);
1357 if (p1 == uid || * p1 != '-')
1358 return MAIL_ERROR_INVAL;
1359
1360 p1++;
1361 num = strtoul(p1, &p2, 10);
1362 if (p2 == p1 || * p2 != '\0')
1363 return MAIL_ERROR_INVAL;
1364
1365 imap = get_imap_session(session);
1366 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1367 return MAIL_ERROR_MSG_NOT_FOUND;
1368
1369 return imapdriver_cached_get_message(session, num, result);
1370}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.h b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
new file mode 100644
index 0000000..c324f5e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_H
37
38#define IMAPDRIVER_CACHED_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * imap_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
new file mode 100644
index 0000000..34e1ca3
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
@@ -0,0 +1,664 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver_message.h"
40#include "imapdriver_cached.h"
41#include "imapdriver_types.h"
42#include "imapdriver.h"
43#include "mailmessage.h"
44#include "generic_cache.h"
45#include "mail_cache_db.h"
46
47#include <string.h>
48#include <stdlib.h>
49
50static int imap_initialize(mailmessage * msg_info);
51
52static void imap_uninitialize(mailmessage * msg_info);
53
54static void imap_flush(mailmessage * msg_info);
55
56static void imap_check(mailmessage * msg_info);
57
58static void imap_fetch_result_free(mailmessage * msg_info,
59 char * msg);
60
61static int imap_fetch(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int imap_fetch_header(mailmessage * msg_info,
66 char ** result,
67 size_t * result_len);
68
69static int imap_fetch_body(mailmessage * msg_info,
70 char ** result, size_t * result_len);
71
72static int imap_fetch_size(mailmessage * msg_info,
73 size_t * result);
74
75static int imap_get_bodystructure(mailmessage * msg_info,
76 struct mailmime ** result);
77
78static int imap_fetch_section(mailmessage * msg_info,
79 struct mailmime * mime,
80 char ** result, size_t * result_len);
81
82static int imap_fetch_section_header(mailmessage * msg_info,
83 struct mailmime * mime,
84 char ** result,
85 size_t * result_len);
86
87static int imap_fetch_section_mime(mailmessage * msg_info,
88 struct mailmime * mime,
89 char ** result,
90 size_t * result_len);
91
92static int imap_fetch_section_body(mailmessage * msg_info,
93 struct mailmime * mime,
94 char ** result,
95 size_t * result_len);
96
97
98static int imap_fetch_envelope(mailmessage * msg_info,
99 struct mailimf_fields ** result);
100
101static int imap_get_flags(mailmessage * msg_info,
102 struct mail_flags ** result);
103
104static mailmessage_driver local_imap_cached_message_driver = {
105 .msg_name = "imap-cached",
106
107 .msg_initialize = imap_initialize,
108 .msg_uninitialize = imap_uninitialize,
109
110 .msg_flush = imap_flush,
111 .msg_check = imap_check,
112
113 .msg_fetch_result_free = imap_fetch_result_free,
114
115 .msg_fetch = imap_fetch,
116 .msg_fetch_header = imap_fetch_header,
117 .msg_fetch_body = imap_fetch_body,
118 .msg_fetch_size = imap_fetch_size,
119 .msg_get_bodystructure = imap_get_bodystructure,
120 .msg_fetch_section = imap_fetch_section,
121 .msg_fetch_section_header = imap_fetch_section_header,
122 .msg_fetch_section_mime = imap_fetch_section_mime,
123 .msg_fetch_section_body = imap_fetch_section_body,
124 .msg_fetch_envelope = imap_fetch_envelope,
125
126 .msg_get_flags = imap_get_flags,
127};
128
129mailmessage_driver * imap_cached_message_driver =
130&local_imap_cached_message_driver;
131
132static inline struct imap_cached_session_state_data *
133get_cached_session_data(mailmessage * msg)
134{
135 return msg->msg_session->sess_data;
136}
137
138static inline mailmessage * get_ancestor(mailmessage * msg_info)
139{
140 return msg_info->msg_data;
141}
142
143static inline struct imap_cached_session_state_data *
144cached_session_get_data(mailsession * s)
145{
146 return s->sess_data;
147}
148
149static inline mailsession * cached_session_get_ancestor(mailsession * s)
150{
151 return cached_session_get_data(s)->imap_ancestor;
152}
153
154static inline struct imap_session_state_data *
155cached_session_get_ancestor_data(mailsession * s)
156{
157 return cached_session_get_ancestor(s)->sess_data;
158}
159
160static inline mailimap *
161cached_session_get_imap_session(mailsession * session)
162{
163 return cached_session_get_ancestor_data(session)->imap_session;
164}
165
166static inline mailimap * get_imap_session(mailmessage * msg)
167{
168 return cached_session_get_imap_session(msg->msg_session);
169}
170
171static inline mailsession * get_ancestor_session(mailmessage * msg_info)
172{
173 return cached_session_get_ancestor(msg_info->msg_session);
174}
175
176
177static void generate_key_from_mime_section(char * key, size_t size,
178 struct mailmime * mime)
179{
180 clistiter * cur;
181 MMAPString * gstr;
182 struct mailmime_section * part;
183 int r;
184
185 snprintf(key, size, "unvalid");
186
187 r = mailmime_get_section_id(mime, &part);
188 if (r != MAILIMF_NO_ERROR)
189 goto err;
190
191 gstr = mmap_string_new("part");
192 if (gstr == NULL)
193 goto free_section;
194
195 for(cur = clist_begin(part->sec_list) ;
196 cur != NULL ; cur = clist_next(cur)) {
197 char s[20];
198
199 snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur));
200 if (mmap_string_append(gstr, s) == NULL)
201 goto free_str;
202 }
203
204 snprintf(key, size, "%s", gstr->str);
205
206 mmap_string_free(gstr);
207 mailmime_section_free(part);
208
209 return;
210
211 free_str:
212 mmap_string_free(gstr);
213 free_section:
214 mailmime_section_free(part);
215 err:;
216}
217
218static void generate_key_from_section(char * key, size_t size,
219 mailmessage * msg_info,
220 struct mailmime * mime, int type)
221{
222 char section_str[PATH_MAX];
223
224 generate_key_from_mime_section(section_str, PATH_MAX, mime);
225
226 switch (type) {
227 case IMAP_SECTION_MESSAGE:
228 snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str);
229 break;
230 case IMAP_SECTION_HEADER:
231 snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str);
232 break;
233 case IMAP_SECTION_MIME:
234 snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str);
235 break;
236 case IMAP_SECTION_BODY:
237 snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str);
238 break;
239 }
240}
241
242static void generate_key_from_message(char * key, size_t size,
243 mailmessage * msg_info,
244 int type)
245{
246 switch (type) {
247 case MAILIMAP_MSG_ATT_RFC822:
248 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
249 break;
250 case MAILIMAP_MSG_ATT_RFC822_HEADER:
251 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
252 break;
253 case MAILIMAP_MSG_ATT_RFC822_TEXT:
254 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
255 break;
256 case MAILIMAP_MSG_ATT_ENVELOPE:
257 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
258 break;
259 }
260}
261
262static void build_cache_name(char * filename, size_t size,
263 mailmessage * msg, char * key)
264{
265 char * quoted_mb;
266
267 quoted_mb = get_cached_session_data(msg)->imap_quoted_mb;
268
269 snprintf(filename, size, "%s/%s", quoted_mb, key);
270}
271
272static int imap_initialize(mailmessage * msg_info)
273{
274 mailmessage * ancestor;
275 int r;
276 char key[PATH_MAX];
277 char * uid;
278 mailimap * imap;
279
280 ancestor = mailmessage_new();
281 if (ancestor == NULL)
282 return MAIL_ERROR_MEMORY;
283
284 r = mailmessage_init(ancestor, get_ancestor_session(msg_info),
285 imap_message_driver,
286 msg_info->msg_index, 0);
287 if (r != MAIL_NO_ERROR) {
288 mailmessage_free(ancestor);
289 return r;
290 }
291
292 imap = get_imap_session(msg_info);
293
294 snprintf(key, PATH_MAX, "%u-%u",
295 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
296 uid = strdup(key);
297 if (uid == NULL) {
298 mailmessage_free(ancestor);
299 return MAIL_ERROR_MEMORY;
300 }
301
302 msg_info->msg_data = ancestor;
303 msg_info->msg_uid = uid;
304
305 return MAIL_NO_ERROR;
306}
307
308static void imap_uninitialize(mailmessage * msg_info)
309{
310 mailmessage_free(get_ancestor(msg_info));
311 msg_info->msg_data = NULL;
312}
313
314static void imap_flush(mailmessage * msg_info)
315{
316 if (msg_info->msg_mime != NULL) {
317 mailmime_free(msg_info->msg_mime);
318 msg_info->msg_mime = NULL;
319 }
320}
321
322static void imap_check(mailmessage * msg_info)
323{
324 get_ancestor(msg_info)->msg_flags = msg_info->msg_flags;
325 mailmessage_check(get_ancestor(msg_info));
326 get_ancestor(msg_info)->msg_flags = NULL;
327}
328
329static void imap_fetch_result_free(mailmessage * msg_info,
330 char * msg)
331{
332 mailmessage_fetch_result_free(get_ancestor(msg_info), msg);
333}
334
335static int imap_fetch(mailmessage * msg_info,
336 char ** result,
337 size_t * result_len)
338{
339 char key[PATH_MAX];
340 char filename[PATH_MAX];
341 int r;
342 char * str;
343 size_t len;
344
345 generate_key_from_message(key, PATH_MAX,
346 msg_info, MAILIMAP_MSG_ATT_RFC822);
347
348 build_cache_name(filename, PATH_MAX, msg_info, key);
349
350 r = generic_cache_read(filename, &str, &len);
351 if (r == MAIL_NO_ERROR) {
352 * result = str;
353 * result_len = len;
354
355 return MAIL_NO_ERROR;
356 }
357
358 r = mailmessage_fetch(get_ancestor(msg_info),
359 result, result_len);
360 if (r == MAIL_NO_ERROR)
361 generic_cache_store(filename, * result, strlen(* result));
362
363 return r;
364}
365
366static int imap_fetch_header(mailmessage * msg_info,
367 char ** result,
368 size_t * result_len)
369{
370 char key[PATH_MAX];
371 char filename[PATH_MAX];
372 int r;
373 char * str;
374 size_t len;
375
376 generate_key_from_message(key, PATH_MAX,
377 msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER);
378
379 build_cache_name(filename, PATH_MAX, msg_info, key);
380
381 r = generic_cache_read(filename, &str, &len);
382 if (r == MAIL_NO_ERROR) {
383 * result = str;
384 * result_len = len;
385
386 return MAIL_NO_ERROR;
387 }
388
389 r = mailmessage_fetch_header(get_ancestor(msg_info), result,
390 result_len);
391 if (r == MAIL_NO_ERROR)
392 generic_cache_store(filename, * result, * result_len);
393
394 return r;
395}
396
397static int imap_fetch_body(mailmessage * msg_info,
398 char ** result, size_t * result_len)
399{
400 char key[PATH_MAX];
401 char filename[PATH_MAX];
402 int r;
403 char * str;
404 size_t len;
405
406 generate_key_from_message(key, PATH_MAX,
407 msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT);
408
409 build_cache_name(filename, PATH_MAX, msg_info, key);
410
411 r = generic_cache_read(filename, &str, &len);
412 if (r == MAIL_NO_ERROR) {
413 * result = str;
414 * result_len = len;
415 return MAIL_NO_ERROR;
416 }
417
418 r = mailmessage_fetch_body(get_ancestor(msg_info), result,
419 result_len);
420 if (r == MAIL_NO_ERROR)
421 generic_cache_store(filename, * result, * result_len);
422
423 return r;
424}
425
426static int imap_fetch_size(mailmessage * msg_info,
427 size_t * result)
428{
429 return mailmessage_fetch_size(get_ancestor(msg_info), result);
430}
431
432static int imap_get_bodystructure(mailmessage * msg_info,
433 struct mailmime ** result)
434{
435 int r;
436
437 if (msg_info->msg_mime != NULL) {
438 * result = msg_info->msg_mime;
439
440 return MAIL_NO_ERROR;
441 }
442
443 r = mailmessage_get_bodystructure(get_ancestor(msg_info),
444 result);
445 if (r == MAIL_NO_ERROR) {
446 msg_info->msg_mime = get_ancestor(msg_info)->msg_mime;
447 get_ancestor(msg_info)->msg_mime = NULL;
448 }
449
450 return r;
451}
452
453static int imap_fetch_section(mailmessage * msg_info,
454 struct mailmime * mime,
455 char ** result, size_t * result_len)
456{
457 char key[PATH_MAX];
458 char filename[PATH_MAX];
459 int r;
460 char * str;
461 size_t len;
462
463 generate_key_from_section(key, PATH_MAX,
464 msg_info, mime, IMAP_SECTION_MESSAGE);
465
466 build_cache_name(filename, PATH_MAX, msg_info, key);
467
468 r = generic_cache_read(filename, &str, &len);
469 if (r == MAIL_NO_ERROR) {
470 * result = str;
471 * result_len = len;
472
473 return MAIL_NO_ERROR;
474 }
475
476 r = mailmessage_fetch_section(get_ancestor(msg_info),
477 mime, result, result_len);
478 if (r == MAIL_NO_ERROR)
479 generic_cache_store(filename, * result, * result_len);
480
481 return r;
482}
483
484static int imap_fetch_section_header(mailmessage * msg_info,
485 struct mailmime * mime,
486 char ** result,
487 size_t * result_len)
488{
489 char key[PATH_MAX];
490 char filename[PATH_MAX];
491 int r;
492 char * str;
493 size_t len;
494
495 generate_key_from_section(key, PATH_MAX,
496 msg_info, mime, IMAP_SECTION_HEADER);
497
498 build_cache_name(filename, PATH_MAX, msg_info, key);
499
500 r = generic_cache_read(filename, &str, &len);
501 if (r == MAIL_NO_ERROR) {
502 * result = str;
503 * result_len = len;
504
505 return MAIL_NO_ERROR;
506 }
507
508 r = mailmessage_fetch_section_header(get_ancestor(msg_info),
509 mime, result, result_len);
510 if (r == MAIL_NO_ERROR)
511 generic_cache_store(filename, * result, * result_len);
512
513 return r;
514}
515
516static int imap_fetch_section_mime(mailmessage * msg_info,
517 struct mailmime * mime,
518 char ** result,
519 size_t * result_len)
520{
521 char key[PATH_MAX];
522 char filename[PATH_MAX];
523 int r;
524 char * str;
525 size_t len;
526
527 generate_key_from_section(key, PATH_MAX,
528 msg_info, mime, IMAP_SECTION_MIME);
529
530 build_cache_name(filename, PATH_MAX, msg_info, key);
531
532 r = generic_cache_read(filename, &str, &len);
533 if (r == MAIL_NO_ERROR) {
534 * result = str;
535 * result_len = len;
536
537 return MAIL_NO_ERROR;
538 }
539
540 r = mailmessage_fetch_section_mime(get_ancestor(msg_info),
541 mime, result, result_len);
542 if (r == MAIL_NO_ERROR)
543 generic_cache_store(filename, * result, * result_len);
544
545 return r;
546}
547
548static int imap_fetch_section_body(mailmessage * msg_info,
549 struct mailmime * mime,
550 char ** result,
551 size_t * result_len)
552{
553 char key[PATH_MAX];
554 char filename[PATH_MAX];
555 int r;
556 char * str;
557 size_t len;
558
559 generate_key_from_section(key, PATH_MAX,
560 msg_info, mime, IMAP_SECTION_BODY);
561
562 build_cache_name(filename, PATH_MAX, msg_info, key);
563
564 r = generic_cache_read(filename, &str, &len);
565 if (r == MAIL_NO_ERROR) {
566
567 * result = str;
568 * result_len = len;
569
570 return MAIL_NO_ERROR;
571 }
572
573 r = mailmessage_fetch_section_body(get_ancestor(msg_info),
574 mime, result, result_len);
575 if (r == MAIL_NO_ERROR)
576 generic_cache_store(filename, * result, * result_len);
577
578 return r;
579}
580
581static int imap_get_flags(mailmessage * msg_info,
582 struct mail_flags ** result)
583{
584 int r;
585 struct mail_flags * flags;
586
587 if (msg_info->msg_flags != NULL) {
588 * result = msg_info->msg_flags;
589 return MAIL_NO_ERROR;
590 }
591
592 r = mailmessage_get_flags(get_ancestor(msg_info), &flags);
593 if (r != MAIL_NO_ERROR)
594 return r;
595
596 get_ancestor(msg_info)->msg_flags = NULL;
597 msg_info->msg_flags = flags;
598 * result = flags;
599
600 return MAIL_NO_ERROR;
601}
602
603#define ENV_NAME "env.db"
604
605static int imap_fetch_envelope(mailmessage * msg_info,
606 struct mailimf_fields ** result)
607{
608 struct mailimf_fields * fields;
609 int r;
610 struct mail_cache_db * cache_db;
611 MMAPString * mmapstr;
612 char filename[PATH_MAX];
613 struct imap_cached_session_state_data * data;
614 int res;
615
616 data = get_cached_session_data(msg_info);
617 if (data->imap_quoted_mb == NULL) {
618 res = MAIL_ERROR_BAD_STATE;
619 goto err;
620 }
621
622 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
623
624 r = mail_cache_db_open_lock(filename, &cache_db);
625 if (r < 0) {
626 res = MAIL_ERROR_MEMORY;
627 goto err;
628 }
629
630 mmapstr = mmap_string_new("");
631 if (mmapstr == NULL) {
632 res = MAIL_ERROR_MEMORY;
633 goto close_db;
634 }
635
636 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
637 msg_info->msg_session, msg_info, &fields);
638
639 if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) {
640 res = r;
641 goto close_db;
642 }
643
644 r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields);
645 if (r != MAIL_NO_ERROR) {
646 res = r;
647 goto close_db;
648 }
649
650 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
651 msg_info->msg_session, msg_info, fields);
652
653 * result = fields;
654
655 mmap_string_free(mmapstr);
656 mail_cache_db_close_unlock(filename, cache_db);
657
658 return MAIL_NO_ERROR;
659
660 close_db:
661 mail_cache_db_close_unlock(filename, cache_db);
662 err:
663 return res;
664}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
new file mode 100644
index 0000000..bf43311
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_MESSAGE_H
37
38#define IMAPDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.c b/libetpan/src/driver/implementation/imap/imapdriver_message.c
new file mode 100644
index 0000000..42e645d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.c
@@ -0,0 +1,1239 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver.h"
40#include "imapdriver_types.h"
41#include "mailimap.h"
42#include "maildriver_tools.h"
43#include "generic_cache.h"
44
45#include <stdlib.h>
46#include <string.h>
47
48static int imap_initialize(mailmessage * msg_info);
49
50static void imap_fetch_result_free(mailmessage * msg_info,
51 char * msg);
52
53static int imap_fetch(mailmessage * msg_info,
54 char ** result,
55 size_t * result_len);
56
57static int imap_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int imap_fetch_body(mailmessage * msg_info,
62 char ** result, size_t * result_len);
63
64static int imap_fetch_size(mailmessage * msg_info,
65 size_t * result);
66
67static int imap_get_bodystructure(mailmessage * msg_info,
68 struct mailmime ** result);
69
70static int imap_fetch_section(mailmessage * msg_info,
71 struct mailmime * mime,
72 char ** result, size_t * result_len);
73
74static int imap_fetch_section_header(mailmessage * msg_info,
75 struct mailmime * mime,
76 char ** result,
77 size_t * result_len);
78
79static int imap_fetch_section_mime(mailmessage * msg_info,
80 struct mailmime * mime,
81 char ** result,
82 size_t * result_len);
83
84static int imap_fetch_section_body(mailmessage * msg_info,
85 struct mailmime * mime,
86 char ** result,
87 size_t * result_len);
88
89static int imap_fetch_envelope(mailmessage * msg_info,
90 struct mailimf_fields ** result);
91
92static int imap_get_flags(mailmessage * msg_info,
93 struct mail_flags ** result);
94
95static void imap_flush(mailmessage * msg_info);
96
97static void imap_check(mailmessage * msg_info);
98
99static mailmessage_driver local_imap_message_driver = {
100 .msg_name = "imap",
101
102 .msg_initialize = imap_initialize,
103 .msg_uninitialize = NULL,
104
105 .msg_flush = imap_flush,
106 .msg_check = imap_check,
107
108 .msg_fetch_result_free = imap_fetch_result_free,
109
110 .msg_fetch = imap_fetch,
111 .msg_fetch_header = imap_fetch_header,
112 .msg_fetch_body = imap_fetch_body,
113 .msg_fetch_size = imap_fetch_size,
114 .msg_get_bodystructure = imap_get_bodystructure,
115 .msg_fetch_section = imap_fetch_section,
116 .msg_fetch_section_header = imap_fetch_section_header,
117 .msg_fetch_section_mime = imap_fetch_section_mime,
118 .msg_fetch_section_body = imap_fetch_section_body,
119 .msg_fetch_envelope = imap_fetch_envelope,
120
121 .msg_get_flags = imap_get_flags,
122};
123
124mailmessage_driver * imap_message_driver = &local_imap_message_driver;
125
126static inline struct imap_session_state_data *
127get_session_data(mailmessage * msg)
128{
129 return msg->msg_session->sess_data;
130}
131
132static inline mailimap * get_imap_session(mailmessage * msg)
133{
134 return get_session_data(msg)->imap_session;
135}
136
137
138
139static int imap_initialize(mailmessage * msg_info)
140{
141 char key[PATH_MAX];
142 char * uid;
143 mailimap * imap;
144
145 imap = get_imap_session(msg_info);
146
147 snprintf(key, PATH_MAX, "%u-%u",
148 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
149
150 uid = strdup(key);
151 if (uid == NULL) {
152 return MAIL_ERROR_MEMORY;
153 }
154
155 msg_info->msg_uid = uid;
156
157 return MAIL_NO_ERROR;
158}
159
160
161static void imap_fetch_result_free(mailmessage * msg_info,
162 char * msg)
163{
164 if (msg != NULL) {
165 if (mmap_string_unref(msg) != 0)
166 free(msg);
167 }
168}
169
170
171static void imap_flush(mailmessage * msg_info)
172{
173 if (msg_info->msg_mime != NULL) {
174 mailmime_free(msg_info->msg_mime);
175 msg_info->msg_mime = NULL;
176 }
177}
178
179static void imap_check(mailmessage * msg_info)
180{
181 int r;
182
183 if (msg_info->msg_flags != NULL) {
184 r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store,
185 msg_info);
186 /* ignore errors */
187 }
188}
189
190static int imap_fetch(mailmessage * msg_info,
191 char ** result,
192 size_t * result_len)
193{
194 int r;
195 struct mailimap_set * set;
196 struct mailimap_fetch_att * fetch_att;
197 struct mailimap_fetch_type * fetch_type;
198 clist * fetch_result;
199 struct mailimap_msg_att * msg_att;
200 struct mailimap_msg_att_item * msg_att_item;
201 char * text;
202 size_t text_length;
203 int res;
204 clistiter * cur;
205 struct mailimap_section * section;
206
207 set = mailimap_set_new_single(msg_info->msg_index);
208 if (set == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213#if 0
214 fetch_att = mailimap_fetch_att_new_rfc822();
215 if (fetch_att == NULL) {
216 res = MAIL_ERROR_MEMORY;
217 goto free_set;
218 }
219
220 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
221 if (fetch_type == NULL) {
222 res = MAIL_ERROR_MEMORY;
223 goto free_fetch_att;
224 }
225
226 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
227 fetch_type, &fetch_result);
228
229 mailimap_fetch_type_free(fetch_type);
230#endif
231
232 section = mailimap_section_new(NULL);
233 if (section == NULL) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_set;
236 }
237
238 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
239 if (fetch_att == NULL) {
240 mailimap_section_free(section);
241 res = MAIL_ERROR_MEMORY;
242 goto free_set;
243 }
244
245 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
246 if (fetch_type == NULL) {
247 res = MAIL_ERROR_MEMORY;
248 goto free_fetch_att;
249 }
250
251 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
252 fetch_type, &fetch_result);
253
254 mailimap_fetch_type_free(fetch_type);
255 mailimap_set_free(set);
256
257 switch (r) {
258 case MAILIMAP_NO_ERROR:
259 break;
260 default:
261 return imap_error_to_mail_error(r);
262 }
263
264 if (clist_begin(fetch_result) == NULL) {
265 mailimap_fetch_list_free(fetch_result);
266 return MAIL_ERROR_FETCH;
267 }
268
269 msg_att = clist_begin(fetch_result)->data;
270
271 text = NULL;
272 text_length = 0;
273
274 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
275 cur = clist_next(cur)) {
276 msg_att_item = clist_content(cur);
277
278 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
279#if 0
280 if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) {
281 text = msg_att_item->msg_att_static->rfc822;
282 msg_att_item->msg_att_static->rfc822 = NULL;
283 text_length = msg_att_item->msg_att_static->length;
284 }
285#endif
286 if (msg_att_item->att_data.att_static->att_type ==
287 MAILIMAP_MSG_ATT_BODY_SECTION) {
288 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
289 /* detach */
290 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
291 text_length =
292 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
293 }
294 }
295 }
296
297 mailimap_fetch_list_free(fetch_result);
298
299 if (text == NULL)
300 return MAIL_ERROR_FETCH;
301
302 * result = text;
303 * result_len = text_length;
304
305 return MAIL_NO_ERROR;
306
307 free_fetch_att:
308 mailimap_fetch_att_free(fetch_att);
309 free_set:
310 mailimap_set_free(set);
311 err:
312 return res;
313}
314
315static int imap_fetch_header(mailmessage * msg_info,
316 char ** result,
317 size_t * result_len)
318{
319 int r;
320 struct mailimap_set * set;
321 struct mailimap_fetch_att * fetch_att;
322 struct mailimap_fetch_type * fetch_type;
323 clist * fetch_result;
324 struct mailimap_msg_att * msg_att;
325 struct mailimap_msg_att_item * msg_att_item;
326 char * text;
327 size_t text_length;
328 int res;
329 clistiter * cur;
330 struct mailimap_section * section;
331
332 set = mailimap_set_new_single(msg_info->msg_index);
333 if (set == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto err;
336 }
337
338#if 0
339 fetch_att = mailimap_fetch_att_new_rfc822_header();
340 if (fetch_att == NULL) {
341 res = MAIL_ERROR_MEMORY;
342 goto free_set;
343 }
344
345 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
346 if (fetch_type == NULL) {
347 res = MAIL_ERROR_MEMORY;
348 goto free_fetch_att;
349 }
350
351 r = mailimap_uid_fetch(get_imap_session(msg_info->session),
352 set, fetch_type, &fetch_result);
353
354 mailimap_fetch_type_free(fetch_type);
355#endif
356
357 section = mailimap_section_new_header();
358 if (section == NULL) {
359 res = MAIL_ERROR_MEMORY;
360 goto free_set;
361 }
362
363 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
364 if (fetch_att == NULL) {
365 mailimap_section_free(section);
366 res = MAIL_ERROR_MEMORY;
367 goto free_set;
368 }
369
370 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
371 if (fetch_type == NULL) {
372 res = MAIL_ERROR_MEMORY;
373 goto free_fetch_att;
374 }
375
376 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
377 fetch_type, &fetch_result);
378
379 mailimap_fetch_type_free(fetch_type);
380 mailimap_set_free(set);
381
382 switch (r) {
383 case MAILIMAP_NO_ERROR:
384 break;
385 default:
386 return imap_error_to_mail_error(r);
387 }
388
389 if (clist_begin(fetch_result) == NULL) {
390 mailimap_fetch_list_free(fetch_result);
391 return MAIL_ERROR_FETCH;
392 }
393
394 msg_att = clist_begin(fetch_result)->data;
395
396 text = NULL;
397 text_length = 0;
398
399 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
400 cur = clist_next(cur)) {
401 msg_att_item = clist_content(cur);
402
403 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
404#if 0
405 if (msg_att_item->msg_att_static->type ==
406 MAILIMAP_MSG_ATT_RFC822_HEADER) {
407 text = msg_att_item->msg_att_static->rfc822_header;
408 msg_att_item->msg_att_static->rfc822_header = NULL;
409 text_length = msg_att_item->msg_att_static->length;
410 }
411#endif
412 if (msg_att_item->att_data.att_static->att_type ==
413 MAILIMAP_MSG_ATT_BODY_SECTION) {
414 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
415 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
416 text_length =
417 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
418 }
419 }
420 }
421
422 mailimap_fetch_list_free(fetch_result);
423
424 if (text == NULL)
425 return MAIL_ERROR_FETCH;
426
427 * result = text;
428 * result_len = text_length;
429
430 return MAIL_NO_ERROR;
431
432 free_fetch_att:
433 mailimap_fetch_att_free(fetch_att);
434 free_set:
435 mailimap_set_free(set);
436 err:
437 return res;
438}
439
440static int imap_fetch_body(mailmessage * msg_info,
441 char ** result, size_t * result_len)
442{
443 int r;
444 struct mailimap_set * set;
445 struct mailimap_fetch_att * fetch_att;
446 struct mailimap_fetch_type * fetch_type;
447 clist * fetch_result;
448 struct mailimap_msg_att * msg_att;
449 struct mailimap_msg_att_item * msg_att_item;
450 char * text;
451 size_t text_length;
452 int res;
453 clistiter * cur;
454 struct mailimap_section * section;
455
456 set = mailimap_set_new_single(msg_info->msg_index);
457 if (set == NULL) {
458 res = MAIL_ERROR_MEMORY;
459 goto err;
460 }
461
462#if 0
463 fetch_att = mailimap_fetch_att_new_rfc822_text();
464 if (fetch_att == NULL) {
465 res = MAIL_ERROR_MEMORY;
466 goto free_set;
467 }
468
469 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
470 if (fetch_type == NULL) {
471 res = MAIL_ERROR_MEMORY;
472 goto free_fetch_att;
473 }
474
475 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
476 fetch_type, &fetch_result);
477
478 mailimap_fetch_type_free(fetch_type);
479#endif
480 section = mailimap_section_new_text();
481 if (section == NULL) {
482 res = MAIL_ERROR_MEMORY;
483 goto free_set;
484 }
485
486 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
487 if (fetch_att == NULL) {
488 mailimap_section_free(section);
489 res = MAIL_ERROR_MEMORY;
490 goto free_set;
491 }
492
493 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
494 if (fetch_type == NULL) {
495 res = MAIL_ERROR_MEMORY;
496 goto free_fetch_att;
497 }
498
499 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
500 fetch_type, &fetch_result);
501
502 mailimap_fetch_type_free(fetch_type);
503 mailimap_set_free(set);
504
505 switch (r) {
506 case MAILIMAP_NO_ERROR:
507 break;
508 default:
509 return imap_error_to_mail_error(r);
510 }
511
512 cur = clist_begin(fetch_result);
513 if (cur == NULL) {
514 mailimap_fetch_list_free(fetch_result);
515 return MAIL_ERROR_FETCH;
516 }
517
518 msg_att = clist_content(cur);
519
520 text = NULL;
521 text_length = 0;
522
523 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
524 cur = clist_next(cur)) {
525 msg_att_item = clist_content(cur);
526
527 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
528#if 0
529 if (msg_att_item->msg_att_static->type ==
530 MAILIMAP_MSG_ATT_RFC822_TEXT) {
531 text = msg_att_item->msg_att_static->rfc822_text;
532 msg_att_item->msg_att_static->rfc822_text = NULL;
533 text_length = msg_att_item->msg_att_static->length;
534 }
535#endif
536 if (msg_att_item->att_data.att_static->att_type ==
537 MAILIMAP_MSG_ATT_BODY_SECTION) {
538 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
539 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
540 text_length =
541 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
542 }
543 }
544 }
545
546 mailimap_fetch_list_free(fetch_result);
547
548 if (text == NULL)
549 return MAIL_ERROR_FETCH;
550
551 * result = text;
552 * result_len = text_length;
553
554 return MAIL_NO_ERROR;
555
556 free_fetch_att:
557 mailimap_fetch_att_free(fetch_att);
558 free_set:
559 mailimap_set_free(set);
560 err:
561 return res;
562}
563
564static int imap_fetch_size(mailmessage * msg_info,
565 size_t * result)
566{
567 int r;
568 struct mailimap_set * set;
569 struct mailimap_fetch_att * fetch_att;
570 struct mailimap_fetch_type * fetch_type;
571 clist * fetch_result;
572 struct mailimap_msg_att * msg_att;
573 struct mailimap_msg_att_item * msg_att_item;
574 size_t size;
575 int res;
576 clistiter * cur;
577
578 set = mailimap_set_new_single(msg_info->msg_index);
579 if (set == NULL) {
580 res = MAIL_ERROR_MEMORY;
581 goto err;
582 }
583
584 fetch_att = mailimap_fetch_att_new_rfc822_size();
585 if (fetch_att == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto free_set;
588 }
589
590 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
591 if (fetch_type == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto free_fetch_att;
594 }
595
596 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
597 fetch_type, &fetch_result);
598
599 mailimap_fetch_type_free(fetch_type);
600 mailimap_set_free(set);
601
602 switch (r) {
603 case MAILIMAP_ERROR_BAD_STATE:
604 return MAIL_ERROR_BAD_STATE;
605 case MAILIMAP_ERROR_STREAM:
606 return MAIL_ERROR_STREAM;
607 case MAILIMAP_NO_ERROR:
608 break;
609 default:
610 return MAIL_ERROR_FETCH;
611 }
612
613 if (clist_begin(fetch_result) == NULL) {
614 mailimap_fetch_list_free(fetch_result);
615 return MAIL_ERROR_FETCH;
616 }
617
618 msg_att = clist_begin(fetch_result)->data;
619
620 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
621 cur = clist_next(cur)) {
622 msg_att_item = clist_content(cur);
623
624 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
625
626 if (msg_att_item->att_data.att_static->att_type ==
627 MAILIMAP_MSG_ATT_RFC822_SIZE) {
628 size = msg_att_item->att_data.att_static->att_data.att_rfc822_size;
629
630 * result = size;
631
632 mailimap_fetch_list_free(fetch_result);
633 return MAIL_NO_ERROR;
634 }
635 }
636 }
637
638 mailimap_fetch_list_free(fetch_result);
639
640 return MAIL_ERROR_FETCH;
641
642 free_fetch_att:
643 mailimap_fetch_att_free(fetch_att);
644 free_set:
645 mailimap_set_free(set);
646 err:
647 return res;
648}
649
650static int imap_get_bodystructure(mailmessage * msg_info,
651 struct mailmime ** result)
652{
653 int r;
654 struct mailimap_set * set;
655 struct mailimap_fetch_att * fetch_att;
656 struct mailimap_fetch_type * fetch_type;
657 clist * fetch_result;
658 struct mailimap_msg_att * msg_att;
659 struct mailimap_body * imap_body;
660 struct mailmime * body;
661 int res;
662 struct mailimf_fields * fields;
663 struct mailmime * new_body;
664 struct mailmime_content * content_message;
665 struct mailimap_envelope * envelope;
666 uint32_t uid;
667 char * references;
668 size_t ref_size;
669 clistiter * cur;
670
671 if (msg_info->msg_mime != NULL) {
672 * result = msg_info->msg_mime;
673
674 return MAIL_NO_ERROR;
675 }
676
677 set = mailimap_set_new_single(msg_info->msg_index);
678 if (set == NULL) {
679 res = MAIL_ERROR_MEMORY;
680 goto err;
681 }
682
683 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
684 if (fetch_type == NULL) {
685 res = MAIL_ERROR_MEMORY;
686 goto free_set;
687 }
688
689 fetch_att = mailimap_fetch_att_new_uid();
690 if (fetch_att == NULL) {
691 res = MAIL_ERROR_MEMORY;
692 goto free_fetch_type;
693 }
694
695 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
696 if (r != MAILIMAP_NO_ERROR) {
697 mailimap_fetch_att_free(fetch_att);
698 res = MAIL_ERROR_MEMORY;
699 goto free_fetch_type;
700 }
701
702 fetch_att = mailimap_fetch_att_new_bodystructure();
703 if (fetch_att == NULL) {
704 res = MAIL_ERROR_MEMORY;
705 goto free_fetch_type;
706 }
707
708 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
709 if (r != MAILIMAP_NO_ERROR) {
710 mailimap_fetch_att_free(fetch_att);
711 res = MAIL_ERROR_MEMORY;
712 goto free_fetch_type;
713 }
714
715 r = imap_add_envelope_fetch_att(fetch_type);
716 if (r != MAIL_NO_ERROR) {
717 res = r;
718 goto free_fetch_type;
719 }
720
721
722 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
723 fetch_type, &fetch_result);
724
725 mailimap_fetch_type_free(fetch_type);
726 mailimap_set_free(set);
727
728 switch (r) {
729 case MAILIMAP_NO_ERROR:
730 break;
731 default:
732 return imap_error_to_mail_error(r);
733 }
734
735 cur = clist_begin(fetch_result);
736 if (cur == NULL) {
737 mailimap_fetch_list_free(fetch_result);
738 return MAIL_ERROR_FETCH;
739 }
740
741 msg_att = clist_content(cur);
742
743 uid = 0;
744 references = NULL;
745 ref_size = 0;
746 imap_body = NULL;
747 envelope = NULL;
748
749 r = imap_get_msg_att_info(msg_att,
750 &uid, &envelope, &references, &ref_size, NULL, &imap_body);
751 if (r != MAIL_NO_ERROR) {
752 mailimap_fetch_list_free(fetch_result);
753 res = r;
754 goto err;
755 }
756
757 if (uid != msg_info->msg_index) {
758 mailimap_fetch_list_free(fetch_result);
759 res = MAIL_ERROR_MSG_NOT_FOUND;
760 goto err;
761 }
762
763 if (imap_body == NULL) {
764 mailimap_fetch_list_free(fetch_result);
765 res = MAIL_ERROR_FETCH;
766 goto err;
767 }
768
769 r = imap_body_to_body(imap_body, &body);
770 if (r != MAIL_NO_ERROR) {
771 mailimap_fetch_list_free(fetch_result);
772 res = r;
773 goto err;
774 }
775
776 fields = NULL;
777 if (envelope != NULL) {
778 r = imap_env_to_fields(envelope, references, ref_size, &fields);
779 if (r != MAIL_NO_ERROR) {
780 mailmime_free(body);
781 mailimap_fetch_list_free(fetch_result);
782 res = r;
783 goto err;
784 }
785 }
786
787 content_message = mailmime_get_content_message();
788 if (content_message == NULL) {
789 if (fields != NULL)
790 mailimf_fields_free(fields);
791 mailmime_free(body);
792 mailimap_fetch_list_free(fetch_result);
793 res = MAIL_ERROR_MEMORY;
794 goto err;
795 }
796
797 new_body = mailmime_new(MAILMIME_MESSAGE, NULL,
798 0, NULL, content_message,
799 NULL, NULL, NULL, NULL, fields, body);
800
801 if (new_body == NULL) {
802 mailmime_content_free(content_message);
803 if (fields != NULL)
804 mailimf_fields_free(fields);
805 mailmime_free(body);
806 mailimap_fetch_list_free(fetch_result);
807 res = MAIL_ERROR_MEMORY;
808 goto err;
809 }
810 msg_info->msg_mime = new_body;
811
812 mailimap_fetch_list_free(fetch_result);
813
814 * result = new_body;
815
816 return MAIL_NO_ERROR;
817
818 free_fetch_type:
819 mailimap_fetch_type_free(fetch_type);
820 free_set:
821 mailimap_set_free(set);
822 err:
823 return res;
824}
825
826static int
827fetch_imap(mailmessage * msg,
828 struct mailimap_fetch_type * fetch_type,
829 char ** result, size_t * result_len)
830{
831 int r;
832 struct mailimap_msg_att * msg_att;
833 struct mailimap_msg_att_item * msg_att_item;
834 clist * fetch_result;
835 struct mailimap_set * set;
836 char * text;
837 size_t text_length;
838 clistiter * cur;
839
840 set = mailimap_set_new_single(msg->msg_index);
841 if (set == NULL)
842 return MAIL_ERROR_MEMORY;
843
844 r = mailimap_uid_fetch(get_imap_session(msg), set,
845 fetch_type, &fetch_result);
846
847 mailimap_set_free(set);
848
849 switch (r) {
850 case MAILIMAP_NO_ERROR:
851 break;
852 default:
853 return imap_error_to_mail_error(r);
854 }
855
856 if (clist_begin(fetch_result) == NULL) {
857 mailimap_fetch_list_free(fetch_result);
858 return MAIL_ERROR_FETCH;
859 }
860
861 msg_att = clist_begin(fetch_result)->data;
862
863 text = NULL;
864 text_length = 0;
865
866 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
867 cur = clist_next(cur)) {
868 msg_att_item = clist_content(cur);
869
870 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
871
872 if (msg_att_item->att_data.att_static->att_type ==
873 MAILIMAP_MSG_ATT_BODY_SECTION) {
874 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
875 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
876 text_length =
877 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
878 }
879 }
880 }
881
882 mailimap_fetch_list_free(fetch_result);
883
884 if (text == NULL)
885 return MAIL_ERROR_FETCH;
886
887 * result = text;
888 * result_len = text_length;
889
890 return MAIL_NO_ERROR;
891}
892
893
894static int imap_fetch_section(mailmessage * msg_info,
895 struct mailmime * mime,
896 char ** result, size_t * result_len)
897{
898 struct mailimap_section * section;
899 struct mailimap_fetch_att * fetch_att;
900 int r;
901 struct mailimap_fetch_type * fetch_type;
902 char * text;
903 size_t text_length;
904 struct mailmime_section * part;
905
906 if (mime->mm_parent == NULL)
907 return imap_fetch(msg_info, result, result_len);
908
909 r = mailmime_get_section_id(mime, &part);
910 if (r != MAILIMF_NO_ERROR)
911 return maildriver_imf_error_to_mail_error(r);
912
913 r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, &section);
914 mailmime_section_free(part);
915 if (r != MAIL_NO_ERROR)
916 return r;
917
918 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
919 if (fetch_att == NULL) {
920 mailimap_section_free(section);
921 return MAIL_ERROR_MEMORY;
922 }
923
924 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
925 if (fetch_type == NULL) {
926 mailimap_fetch_att_free(fetch_att);
927 return MAIL_ERROR_MEMORY;
928 }
929
930 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
931
932 mailimap_fetch_type_free(fetch_type);
933
934 if (r != MAIL_NO_ERROR)
935 return r;
936
937 * result = text;
938 * result_len = text_length;
939
940 return MAIL_NO_ERROR;
941}
942
943static int imap_fetch_section_header(mailmessage * msg_info,
944 struct mailmime * mime,
945 char ** result,
946 size_t * result_len)
947{
948 struct mailimap_section * section;
949 struct mailimap_fetch_att * fetch_att;
950 int r;
951 struct mailimap_fetch_type * fetch_type;
952 char * text;
953 size_t text_length;
954 struct mailmime_section * part;
955
956 if (mime->mm_parent == NULL)
957 return imap_fetch_header(msg_info, result, result_len);
958
959 r = mailmime_get_section_id(mime, &part);
960 if (r != MAILIMF_NO_ERROR)
961 return maildriver_imf_error_to_mail_error(r);
962
963 r = section_to_imap_section(part, IMAP_SECTION_HEADER, &section);
964 mailmime_section_free(part);
965 if (r != MAIL_NO_ERROR)
966 return r;
967
968 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
969 if (fetch_att == NULL) {
970 mailimap_section_free(section);
971 return MAIL_ERROR_MEMORY;
972 }
973
974 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
975 if (fetch_type == NULL) {
976 mailimap_fetch_att_free(fetch_att);
977 return MAIL_ERROR_MEMORY;
978 }
979
980 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
981 mailimap_fetch_type_free(fetch_type);
982
983 if (r != MAIL_NO_ERROR)
984 return r;
985
986 * result = text;
987 * result_len = text_length;
988
989 return MAIL_NO_ERROR;
990}
991
992static int imap_fetch_section_mime(mailmessage * msg_info,
993 struct mailmime * mime,
994 char ** result,
995 size_t * result_len)
996{
997 struct mailimap_section * section;
998 struct mailimap_fetch_att * fetch_att;
999 int r;
1000 struct mailimap_fetch_type * fetch_type;
1001 char * text;
1002 size_t text_length;
1003 struct mailmime_section * part;
1004
1005 if (mime->mm_parent == NULL)
1006 return MAIL_ERROR_INVAL;
1007
1008 if (mime->mm_parent->mm_parent == NULL)
1009 return imap_fetch_header(msg_info, result, result_len);
1010
1011 r = mailmime_get_section_id(mime, &part);
1012 if (r != MAILIMF_NO_ERROR)
1013 return maildriver_imf_error_to_mail_error(r);
1014
1015 r = section_to_imap_section(part, IMAP_SECTION_MIME, &section);
1016 mailmime_section_free(part);
1017 if (r != MAIL_NO_ERROR)
1018 return MAIL_ERROR_MEMORY;
1019
1020 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1021 if (fetch_att == NULL) {
1022 mailimap_section_free(section);
1023 return MAIL_ERROR_MEMORY;
1024 }
1025
1026 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1027 if (fetch_type == NULL) {
1028 mailimap_fetch_att_free(fetch_att);
1029 return MAIL_ERROR_MEMORY;
1030 }
1031
1032 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1033
1034 mailimap_fetch_type_free(fetch_type);
1035
1036 if (r != MAIL_NO_ERROR)
1037 return r;
1038
1039 * result = text;
1040 * result_len = text_length;
1041
1042 return MAIL_NO_ERROR;
1043}
1044
1045static int imap_fetch_section_body(mailmessage * msg_info,
1046 struct mailmime * mime,
1047 char ** result,
1048 size_t * result_len)
1049{
1050 struct mailimap_section * section;
1051 struct mailimap_fetch_att * fetch_att;
1052 int r;
1053 struct mailimap_fetch_type * fetch_type;
1054 char * text;
1055 size_t text_length;
1056 struct mailmime_section * part;
1057
1058 if (mime->mm_parent == NULL)
1059 return imap_fetch_body(msg_info, result, result_len);
1060
1061 if (mime->mm_parent->mm_parent == NULL)
1062 return imap_fetch_body(msg_info, result, result_len);
1063
1064 r = mailmime_get_section_id(mime, &part);
1065 if (r != MAILIMF_NO_ERROR)
1066 return maildriver_imf_error_to_mail_error(r);
1067
1068 r = section_to_imap_section(part, IMAP_SECTION_BODY, &section);
1069 mailmime_section_free(part);
1070 if (r != MAIL_NO_ERROR)
1071 return MAIL_ERROR_MEMORY;
1072
1073 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1074 if (fetch_att == NULL) {
1075 mailimap_section_free(section);
1076 return MAIL_ERROR_MEMORY;
1077 }
1078
1079 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1080 if (fetch_type == NULL) {
1081 mailimap_fetch_att_free(fetch_att);
1082 return MAIL_ERROR_MEMORY;
1083 }
1084
1085 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1086
1087 mailimap_fetch_type_free(fetch_type);
1088
1089 if (r != MAIL_NO_ERROR)
1090 return r;
1091
1092 * result = text;
1093 * result_len = text_length;
1094
1095 return MAIL_NO_ERROR;
1096}
1097
1098static int imap_get_flags(mailmessage * msg_info,
1099 struct mail_flags ** result)
1100{
1101 int r;
1102 struct mail_flags * flags;
1103
1104 if (msg_info->msg_flags != NULL) {
1105 * result = msg_info->msg_flags;
1106 return MAIL_NO_ERROR;
1107 }
1108
1109 flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store,
1110 msg_info->msg_index);
1111
1112 if (flags == NULL) {
1113 r = imap_fetch_flags(get_imap_session(msg_info),
1114 msg_info->msg_index, &flags);
1115 if (r != MAIL_NO_ERROR)
1116 return r;
1117 }
1118
1119 msg_info->msg_flags = flags;
1120
1121 * result = flags;
1122
1123 return MAIL_NO_ERROR;
1124}
1125
1126static int imap_fetch_envelope(mailmessage * msg_info,
1127 struct mailimf_fields ** result)
1128{
1129 int r;
1130 struct mailimap_set * set;
1131 struct mailimap_fetch_att * fetch_att;
1132 struct mailimap_fetch_type * fetch_type;
1133 clist * fetch_result;
1134 struct mailimap_msg_att * msg_att;
1135 int res;
1136 struct mailimf_fields * fields;
1137 struct mailimap_envelope * envelope;
1138 uint32_t uid;
1139 char * references;
1140 size_t ref_size;
1141
1142 set = mailimap_set_new_single(msg_info->msg_index);
1143 if (set == NULL) {
1144 res = MAIL_ERROR_MEMORY;
1145 goto err;
1146 }
1147
1148 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1149 if (fetch_type == NULL) {
1150 res = MAIL_ERROR_MEMORY;
1151 goto free_set;
1152 }
1153
1154 fetch_att = mailimap_fetch_att_new_uid();
1155 if (fetch_att == NULL) {
1156 res = MAIL_ERROR_MEMORY;
1157 goto free_fetch_type;
1158 }
1159
1160 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1161 if (r != MAILIMAP_NO_ERROR) {
1162 mailimap_fetch_att_free(fetch_att);
1163 res = MAIL_ERROR_MEMORY;
1164 goto free_fetch_type;
1165 }
1166
1167 r = imap_add_envelope_fetch_att(fetch_type);
1168 if (r != MAIL_NO_ERROR) {
1169 res = r;
1170 goto free_fetch_type;
1171 }
1172
1173 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
1174 fetch_type, &fetch_result);
1175
1176 mailimap_fetch_type_free(fetch_type);
1177 mailimap_set_free(set);
1178
1179 switch (r) {
1180 case MAILIMAP_NO_ERROR:
1181 break;
1182 default:
1183 return imap_error_to_mail_error(r);
1184 }
1185
1186 if (clist_begin(fetch_result) == NULL) {
1187 mailimap_fetch_list_free(fetch_result);
1188 return MAIL_ERROR_FETCH;
1189 }
1190
1191 msg_att = clist_begin(fetch_result)->data;
1192
1193 uid = 0;
1194 references = NULL;
1195 ref_size = 0;
1196 envelope = NULL;
1197
1198 r = imap_get_msg_att_info(msg_att,
1199 &uid,
1200 &envelope,
1201 &references,
1202 &ref_size,
1203 NULL,
1204 NULL);
1205 if (r != MAIL_NO_ERROR) {
1206 mailimap_fetch_list_free(fetch_result);
1207 res = r;
1208 goto err;
1209 }
1210
1211 if (uid != msg_info->msg_index) {
1212 mailimap_fetch_list_free(fetch_result);
1213 res = MAIL_ERROR_MSG_NOT_FOUND;
1214 goto err;
1215 }
1216
1217 fields = NULL;
1218 if (envelope != NULL) {
1219 r = imap_env_to_fields(envelope, references, ref_size, &fields);
1220 if (r != MAIL_NO_ERROR) {
1221 mailimap_fetch_list_free(fetch_result);
1222 res = r;
1223 goto err;
1224 }
1225 }
1226
1227 mailimap_fetch_list_free(fetch_result);
1228
1229 * result = fields;
1230
1231 return MAIL_NO_ERROR;
1232
1233 free_fetch_type:
1234 mailimap_fetch_type_free(fetch_type);
1235 free_set:
1236 mailimap_set_free(set);
1237 err:
1238 return res;
1239}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.h b/libetpan/src/driver/implementation/imap/imapdriver_message.h
new file mode 100644
index 0000000..74fc2e6
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_MESSAGE_H
37
38#define IMAPDRIVER_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.c b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
new file mode 100644
index 0000000..6051281
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
@@ -0,0 +1,3623 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_tools.h"
37
38#include "maildriver.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43#include "mail.h"
44#include "imapdriver_types.h"
45#include "maildriver_tools.h"
46#include "generic_cache.h"
47#include "mailmessage.h"
48#include "mail_cache_db.h"
49
50
51
52static inline struct imap_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct imap_cached_session_state_data *
59cached_session_get_data(mailsession * session)
60{
61 return session->sess_data;
62}
63
64static inline mailsession *
65cached_session_get_ancestor(mailsession * session)
66{
67 return cached_session_get_data(session)->imap_ancestor;
68}
69
70static inline struct imap_session_state_data *
71cached_session_get_ancestor_data(mailsession * session)
72{
73 return session_get_data(cached_session_get_ancestor(session));
74}
75
76static inline mailimap *
77cached_session_get_imap_session(mailsession * session)
78{
79 return cached_session_get_ancestor_data(session)->imap_session;
80}
81
82static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
83 struct mail_flags ** result);
84
85
86int imap_error_to_mail_error(int error)
87{
88 switch (error) {
89 case MAILIMAP_NO_ERROR:
90 return MAIL_NO_ERROR;
91
92 case MAILIMAP_NO_ERROR_AUTHENTICATED:
93 return MAIL_NO_ERROR_AUTHENTICATED;
94
95 case MAILIMAP_NO_ERROR_NON_AUTHENTICATED:
96 return MAIL_NO_ERROR_NON_AUTHENTICATED;
97
98 case MAILIMAP_ERROR_BAD_STATE:
99 return MAIL_ERROR_BAD_STATE;
100
101 case MAILIMAP_ERROR_STREAM:
102 return MAIL_ERROR_STREAM;
103
104 case MAILIMAP_ERROR_PARSE:
105 return MAIL_ERROR_PARSE;
106
107 case MAILIMAP_ERROR_CONNECTION_REFUSED:
108 return MAIL_ERROR_CONNECT;
109
110 case MAILIMAP_ERROR_MEMORY:
111 return MAIL_ERROR_MEMORY;
112
113 case MAILIMAP_ERROR_FATAL:
114 return MAIL_ERROR_FATAL;
115
116 case MAILIMAP_ERROR_PROTOCOL:
117 return MAIL_ERROR_PROTOCOL;
118
119 case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION:
120 return MAIL_ERROR_CONNECT;
121
122 case MAILIMAP_ERROR_APPEND:
123 return MAIL_ERROR_APPEND;
124
125 case MAILIMAP_ERROR_NOOP:
126 return MAIL_ERROR_NOOP;
127
128 case MAILIMAP_ERROR_LOGOUT:
129 return MAIL_ERROR_LOGOUT;
130
131 case MAILIMAP_ERROR_CAPABILITY:
132 return MAIL_ERROR_CAPABILITY;
133
134 case MAILIMAP_ERROR_CHECK:
135 return MAIL_ERROR_CHECK;
136
137 case MAILIMAP_ERROR_CLOSE:
138 return MAIL_ERROR_CLOSE;
139
140 case MAILIMAP_ERROR_EXPUNGE:
141 return MAIL_ERROR_EXPUNGE;
142
143 case MAILIMAP_ERROR_COPY:
144 case MAILIMAP_ERROR_UID_COPY:
145 return MAIL_ERROR_COPY;
146
147 case MAILIMAP_ERROR_CREATE:
148 return MAIL_ERROR_CREATE;
149
150 case MAILIMAP_ERROR_DELETE:
151 return MAIL_ERROR_DELETE;
152
153 case MAILIMAP_ERROR_EXAMINE:
154 return MAIL_ERROR_EXAMINE;
155
156 case MAILIMAP_ERROR_FETCH:
157 case MAILIMAP_ERROR_UID_FETCH:
158 return MAIL_ERROR_FETCH;
159
160 case MAILIMAP_ERROR_LIST:
161 return MAIL_ERROR_LIST;
162
163 case MAILIMAP_ERROR_LOGIN:
164 return MAIL_ERROR_LOGIN;
165
166 case MAILIMAP_ERROR_LSUB:
167 return MAIL_ERROR_LSUB;
168
169 case MAILIMAP_ERROR_RENAME:
170 return MAIL_ERROR_RENAME;
171
172 case MAILIMAP_ERROR_SEARCH:
173 case MAILIMAP_ERROR_UID_SEARCH:
174 return MAIL_ERROR_SEARCH;
175
176 case MAILIMAP_ERROR_SELECT:
177 return MAIL_ERROR_SELECT;
178
179 case MAILIMAP_ERROR_STATUS:
180 return MAIL_ERROR_STATUS;
181
182 case MAILIMAP_ERROR_STORE:
183 case MAILIMAP_ERROR_UID_STORE:
184 return MAIL_ERROR_STORE;
185
186 case MAILIMAP_ERROR_SUBSCRIBE:
187 return MAIL_ERROR_SUBSCRIBE;
188
189 case MAILIMAP_ERROR_UNSUBSCRIBE:
190 return MAIL_ERROR_UNSUBSCRIBE;
191
192 case MAILIMAP_ERROR_STARTTLS:
193 return MAIL_ERROR_STARTTLS;
194
195 case MAILIMAP_ERROR_INVAL:
196 return MAIL_ERROR_INVAL;
197
198 default:
199 return MAIL_ERROR_INVAL;
200 }
201}
202
203
204
205
206
207static int
208imap_body_parameter_to_content(struct mailimap_body_fld_param *
209 body_parameter,
210 char * subtype,
211 struct mailmime_type * mime_type,
212 struct mailmime_content ** result);
213
214static int
215imap_body_type_text_to_content_type(char * subtype,
216 struct mailimap_body_fld_param *
217 body_parameter,
218 struct mailmime_content ** result);
219
220
221int imap_list_to_list(clist * imap_list, struct mail_list ** result)
222{
223 clistiter * cur;
224 clist * list;
225 struct mail_list * resp;
226 int r;
227 int res;
228
229 list = clist_new();
230 if (list == NULL) {
231 res = MAIL_ERROR_MEMORY;
232 goto err;
233 }
234
235 for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) {
236 struct mailimap_mailbox_list * mb_list;
237 char * new_mb;
238
239 mb_list = clist_content(cur);
240
241 new_mb = strdup(mb_list->mb_name);
242 if (new_mb == NULL) {
243 res = MAIL_ERROR_MEMORY;
244 goto free_list;
245 }
246
247 r = clist_append(list, new_mb);
248 if (r != 0) {
249 free(new_mb);
250 res = MAIL_ERROR_MEMORY;
251 goto free_list;
252 }
253 }
254
255 resp = mail_list_new(list);
256 if (resp == NULL) {
257 res = MAIL_ERROR_MEMORY;
258 goto free_list;
259 }
260
261 * result = resp;
262
263 return MAIL_NO_ERROR;
264
265 free_list:
266 clist_foreach(list, (clist_func) free, NULL);
267 clist_free(list);
268 err:
269 return res;
270}
271
272int
273section_to_imap_section(struct mailmime_section * section, int type,
274 struct mailimap_section ** result)
275{
276 struct mailimap_section_part * section_part;
277 struct mailimap_section * imap_section;
278 clist * list;
279 clistiter * cur;
280 int r;
281 int res;
282
283 list = clist_new();
284 if (list == NULL) {
285 res = MAIL_ERROR_MEMORY;
286 goto err;
287 }
288
289 for(cur = clist_begin(section->sec_list) ; cur != NULL ;
290 cur = clist_next(cur)) {
291 uint32_t value;
292 uint32_t * id;
293
294 value = * (uint32_t *) clist_content(cur);
295 id = malloc(sizeof(* id));
296 if (id == NULL) {
297 res = MAIL_ERROR_MEMORY;
298 goto free_list;
299 }
300 * id = value;
301 r = clist_append(list, id);
302 if (r != 0) {
303 res = MAIL_ERROR_MEMORY;
304 free(id);
305 goto free_list;
306 }
307 }
308
309 section_part = mailimap_section_part_new(list);
310 if (section_part == NULL) {
311 res = MAIL_ERROR_MEMORY;
312 goto free_list;
313 }
314
315 imap_section = NULL;
316
317 switch (type) {
318 case IMAP_SECTION_MESSAGE:
319 imap_section = mailimap_section_new_part(section_part);
320 break;
321 case IMAP_SECTION_HEADER:
322 imap_section = mailimap_section_new_part_header(section_part);
323 break;
324 case IMAP_SECTION_MIME:
325 imap_section = mailimap_section_new_part_mime(section_part);
326 break;
327 case IMAP_SECTION_BODY:
328 imap_section = mailimap_section_new_part_text(section_part);
329 break;
330 }
331
332 if (imap_section == NULL) {
333 res = MAIL_ERROR_MEMORY;
334 goto free_part;
335 }
336
337 * result = imap_section;
338
339 return MAIL_NO_ERROR;
340
341 free_part:
342 mailimap_section_part_free(section_part);
343 free_list:
344 if (list != NULL) {
345 clist_foreach(list, (clist_func) free, NULL);
346 clist_free(list);
347 }
348 err:
349 return res;
350}
351
352
353
354static int
355imap_body_media_basic_to_content_type(struct mailimap_media_basic *
356 media_basic,
357 struct mailimap_body_fld_param *
358 body_parameter,
359 struct mailmime_content ** result)
360{
361 struct mailmime_content * content;
362 struct mailmime_type * mime_type;
363 struct mailmime_discrete_type * discrete_type;
364 struct mailmime_composite_type * composite_type;
365 char * discrete_type_extension;
366 int discrete_type_type;
367 int composite_type_type;
368 int mime_type_type;
369 char * subtype;
370 int r;
371 int res;
372
373 discrete_type = NULL;
374 composite_type = NULL;
375 discrete_type_extension = NULL;
376 subtype = NULL;
377 discrete_type_type = 0;
378 composite_type_type = 0;
379 mime_type_type = 0;
380
381 switch (media_basic->med_type) {
382 case MAILIMAP_MEDIA_BASIC_APPLICATION:
383 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
384 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
385 break;
386
387 case MAILIMAP_MEDIA_BASIC_AUDIO:
388 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
389 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
390 break;
391
392 case MAILIMAP_MEDIA_BASIC_IMAGE:
393 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
394 discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE;
395 break;
396
397 case MAILIMAP_MEDIA_BASIC_MESSAGE:
398 mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE;
399 composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE;
400 break;
401
402 case MAILIMAP_MEDIA_BASIC_VIDEO:
403 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
404 discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO;
405 break;
406
407 case MAILIMAP_MEDIA_BASIC_OTHER:
408 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
409 discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION;
410 discrete_type_extension = media_basic->med_basic_type;
411 if (discrete_type_extension == NULL) {
412 res = MAIL_ERROR_INVAL;
413 goto err;
414 }
415
416 break;
417
418 default:
419 res = MAIL_ERROR_INVAL;
420 goto err;
421 }
422
423 switch (mime_type_type) {
424 case MAILMIME_TYPE_DISCRETE_TYPE:
425 if (discrete_type_extension != NULL) {
426 discrete_type_extension = strdup(discrete_type_extension);
427 if (discrete_type_extension == NULL) {
428 res = MAIL_ERROR_MEMORY;
429 goto err;
430 }
431 }
432
433 discrete_type = mailmime_discrete_type_new(discrete_type_type,
434 discrete_type_extension);
435 if (discrete_type == NULL) {
436 if (discrete_type_extension != NULL)
437 free(discrete_type_extension);
438 res = MAIL_ERROR_MEMORY;
439 goto err;
440 }
441
442 break;
443
444 case MAILMIME_TYPE_COMPOSITE_TYPE:
445 composite_type = mailmime_composite_type_new(composite_type_type,
446 NULL);
447 if (composite_type == NULL) {
448 res = MAIL_ERROR_MEMORY;
449 goto err;
450 }
451
452 break;
453
454 default:
455 res = MAIL_ERROR_INVAL;
456 goto err;
457 }
458
459 mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type);
460 if (mime_type == NULL) {
461 res = MAIL_ERROR_MEMORY;
462 goto free;
463 }
464
465 r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype,
466 mime_type, &content);
467 if (r != MAIL_NO_ERROR) {
468 res = r;
469 goto free_type;
470 }
471
472 * result = content;
473
474 return MAIL_NO_ERROR;
475
476 free_type:
477 mailmime_type_free(mime_type);
478 free:
479 if (discrete_type != NULL)
480 mailmime_discrete_type_free(discrete_type);
481 if (composite_type != NULL)
482 mailmime_composite_type_free(composite_type);
483 err:
484 return res;
485}
486
487static int
488imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp,
489 struct mailmime_disposition ** result)
490{
491 size_t cur_token;
492 int r;
493 struct mailmime_disposition_type * dsp_type;
494 struct mailmime_disposition * dsp;
495 clist * parameters;
496 int res;
497
498 cur_token = 0;
499 r = mailmime_disposition_type_parse(imap_dsp->dsp_type,
500 strlen(imap_dsp->dsp_type), &cur_token, &dsp_type);
501 if (r != MAILIMF_NO_ERROR) {
502 res = MAILIMF_ERROR_PARSE;
503 goto err;
504 }
505
506 parameters = clist_new();
507 if (parameters == NULL) {
508 res = MAIL_ERROR_MEMORY;
509 goto err;
510 }
511
512 if (imap_dsp->dsp_attributes != NULL) {
513 clistiter * cur;
514
515 for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ;
516 cur = clist_next(cur)) {
517 struct mailimap_single_body_fld_param * imap_param;
518 struct mailmime_disposition_parm * dsp_param;
519 struct mailmime_parameter * param;
520 char * filename;
521 char * creation_date;
522 char * modification_date;
523 char * read_date;
524 size_t size;
525 int type;
526
527 imap_param = clist_content(cur);
528
529 filename = NULL;
530 creation_date = NULL;
531 modification_date = NULL;
532 read_date = NULL;
533 size = 0;
534 param = NULL;
535
536 type = mailmime_disposition_guess_type(imap_param->pa_name,
537 strlen(imap_param->pa_name), 0);
538
539 switch (type) {
540 case MAILMIME_DISPOSITION_PARM_FILENAME:
541 if (strcasecmp(imap_param->pa_name, "filename") != 0) {
542 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
543 break;
544 }
545 filename = strdup(imap_param->pa_value);
546 if (filename == NULL) {
547 res = MAIL_ERROR_MEMORY;
548 goto free_dsp_type;
549 }
550 break;
551
552 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
553 if (strcasecmp(imap_param->pa_name, "creation-date") != 0) {
554 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
555 break;
556 }
557 creation_date = strdup(imap_param->pa_value);
558 if (creation_date == NULL) {
559 res = MAIL_ERROR_MEMORY;
560 goto free_dsp_type;
561 }
562 break;
563
564 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
565 if (strcasecmp(imap_param->pa_name, "modification-date") != 0) {
566 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
567 break;
568 }
569 modification_date = strdup(imap_param->pa_value);
570 if (modification_date == NULL) {
571 res = MAIL_ERROR_MEMORY;
572 goto free_dsp_type;
573 }
574 break;
575
576 case MAILMIME_DISPOSITION_PARM_READ_DATE:
577 if (strcasecmp(imap_param->pa_name, "read-date") != 0) {
578 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
579 break;
580 }
581 read_date = strdup(imap_param->pa_value);
582 if (read_date == NULL) {
583 res = MAIL_ERROR_MEMORY;
584 goto free_dsp_type;
585 }
586 break;
587
588 case MAILMIME_DISPOSITION_PARM_SIZE:
589 if (strcasecmp(imap_param->pa_name, "size") != 0) {
590 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
591 break;
592 }
593 size = strtoul(imap_param->pa_value, NULL, 10);
594 break;
595 }
596
597 if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
598 char * name;
599 char * value;
600
601 name = strdup(imap_param->pa_name);
602 if (name == NULL) {
603 res = MAIL_ERROR_MEMORY;
604 goto free_dsp_type;
605 }
606
607 value = strdup(imap_param->pa_value);
608 if (value == NULL) {
609 res = MAIL_ERROR_MEMORY;
610 free(name);
611 goto free_dsp_type;
612 }
613
614 param = mailmime_parameter_new(name, value);
615 if (param == NULL) {
616 free(value);
617 free(name);
618 res = MAIL_ERROR_MEMORY;
619 goto free_dsp_type;
620 }
621
622 }
623
624 dsp_param = mailmime_disposition_parm_new(type, filename,
625 creation_date,
626 modification_date,
627 read_date,
628 size, param);
629 if (dsp_param == NULL) {
630 if (filename != NULL)
631 free(filename);
632 if (creation_date != NULL)
633 free(creation_date);
634 if (modification_date != NULL)
635 free(modification_date);
636 if (read_date != NULL)
637 free(read_date);
638 if (param != NULL)
639 mailmime_parameter_free(param);
640 res = MAIL_ERROR_MEMORY;
641 goto free_list;
642 }
643
644 r = clist_append(parameters, dsp_param);
645 if (r != 0) {
646 mailmime_disposition_parm_free(dsp_param);
647 res = MAIL_ERROR_MEMORY;
648 goto free_list;
649 }
650 }
651 }
652
653 dsp = mailmime_disposition_new(dsp_type, parameters);
654 if (dsp == NULL) {
655 res = MAIL_ERROR_MEMORY;
656 goto free_list;
657 }
658
659 * result = dsp;
660
661 return MAIL_NO_ERROR;
662
663 free_list:
664 clist_foreach(parameters,
665 (clist_func) mailmime_disposition_parm_free, NULL);
666 clist_free(parameters);
667 free_dsp_type:
668 mailmime_disposition_type_free(dsp_type);
669 err:
670 return res;
671}
672
673static int
674imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang,
675 struct mailmime_language ** result)
676{
677 clist * list;
678 clistiter * cur;
679 int res;
680 char * single;
681 int r;
682 struct mailmime_language * lang;
683
684 list = clist_new();
685 if (list == NULL) {
686 res = MAIL_ERROR_MEMORY;
687 goto err;
688 }
689
690 switch (imap_lang->lg_type) {
691 case MAILIMAP_BODY_FLD_LANG_SINGLE:
692 if (imap_lang->lg_data.lg_single != NULL) {
693 single = strdup(imap_lang->lg_data.lg_single);
694 if (single == NULL) {
695 res = MAIL_ERROR_MEMORY;
696 goto free;
697 }
698 r = clist_append(list, single);
699 if (r < 0) {
700 free(single);
701 res = MAIL_ERROR_MEMORY;
702 goto free;
703 }
704 }
705
706 break;
707
708 case MAILIMAP_BODY_FLD_LANG_LIST:
709 for(cur = clist_begin(imap_lang->lg_data.lg_list) ;
710 cur != NULL ; cur = clist_next(cur)) {
711 single = strdup(clist_content(cur));
712 if (single == NULL) {
713 res = MAIL_ERROR_MEMORY;
714 goto free;
715 }
716 r = clist_append(list, single);
717 if (r < 0) {
718 free(single);
719 res = MAIL_ERROR_MEMORY;
720 goto free;
721 }
722 }
723 }
724
725 lang = mailmime_language_new(list);
726 if (lang == NULL) {
727 res = MAIL_ERROR_MEMORY;
728 goto free;
729 }
730
731 * result = lang;
732
733 return MAIL_NO_ERROR;
734
735 free:
736 clist_foreach(list, (clist_func) free, NULL);
737 clist_free(list);
738 err:
739 return res;
740}
741
742static int
743imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields,
744 struct mailimap_body_fld_dsp * imap_dsp,
745 struct mailimap_body_fld_lang * imap_lang,
746 struct mailmime_fields ** result,
747 uint32_t * pbody_size)
748{
749 struct mailmime_field * mime_field;
750 struct mailmime_fields * mime_fields;
751 clist * list;
752 char * id;
753 struct mailmime_mechanism * encoding;
754 char * description;
755 struct mailmime_disposition * dsp;
756 struct mailmime_language * lang;
757 int type;
758 int r;
759 int res;
760
761 list = clist_new();
762 if (list == NULL) {
763 res = MAIL_ERROR_MEMORY;
764 goto err;
765 }
766
767 if (body_fields != NULL) {
768
769 if (pbody_size != NULL)
770 * pbody_size = body_fields->bd_size;
771
772 if (body_fields->bd_id != NULL) {
773 type = MAILMIME_FIELD_ID;
774 id = strdup(body_fields->bd_id);
775 if (id == NULL) {
776 res = MAIL_ERROR_MEMORY;
777 goto free_list;
778 }
779
780 mime_field = mailmime_field_new(type, NULL,
781 NULL, id, NULL, 0, NULL, NULL);
782 if (mime_field == NULL) {
783 free(id);
784 res = MAIL_ERROR_MEMORY;
785 goto free_list;
786 }
787
788 r = clist_append(list, mime_field);
789 if (r != 0) {
790 mailmime_field_free(mime_field);
791 res = MAIL_ERROR_MEMORY;
792 goto free_list;
793 }
794 }
795
796 if (body_fields->bd_description != NULL) {
797 type = MAILMIME_FIELD_DESCRIPTION;
798 description = strdup(body_fields->bd_description);
799 if (description == NULL) {
800 res = MAIL_ERROR_MEMORY;
801 goto free_list;
802 }
803
804 mime_field = mailmime_field_new(type, NULL,
805 NULL, NULL, description, 0, NULL, NULL);
806 if (mime_field == NULL) {
807 free(description);
808 res = MAIL_ERROR_MEMORY;
809 goto free_list;
810 }
811
812 r = clist_append(list, mime_field);
813 if (r != 0) {
814 mailmime_field_free(mime_field);
815 res = MAIL_ERROR_MEMORY;
816 goto free_list;
817 }
818 }
819
820 if (body_fields->bd_encoding != NULL) {
821 char * encoding_value;
822 int encoding_type;
823
824 type = MAILMIME_FIELD_TRANSFER_ENCODING;
825
826 encoding_value = NULL;
827 switch (body_fields->bd_encoding->enc_type) {
828 case MAILIMAP_BODY_FLD_ENC_7BIT:
829 encoding_type = MAILMIME_MECHANISM_7BIT;
830 break;
831 case MAILIMAP_BODY_FLD_ENC_8BIT:
832 encoding_type = MAILMIME_MECHANISM_8BIT;
833 break;
834 case MAILIMAP_BODY_FLD_ENC_BINARY:
835 encoding_type = MAILMIME_MECHANISM_BINARY;
836 break;
837 case MAILIMAP_BODY_FLD_ENC_BASE64:
838 encoding_type = MAILMIME_MECHANISM_BASE64;
839 break;
840 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
841 encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
842 break;
843 case MAILIMAP_BODY_FLD_ENC_OTHER:
844 encoding_type = MAILMIME_MECHANISM_TOKEN;
845 encoding_value = strdup(body_fields->bd_encoding->enc_value);
846 if (encoding_value == NULL) {
847 res = MAIL_ERROR_MEMORY;
848 goto free_list;
849 }
850 break;
851 default:
852 res = MAIL_ERROR_INVAL;
853 goto free_list;
854 }
855
856 encoding = mailmime_mechanism_new(encoding_type, encoding_value);
857 if (encoding == NULL) {
858 if (encoding_value != NULL)
859 free(encoding_value);
860 res = MAIL_ERROR_MEMORY;
861 goto free_list;
862 }
863
864 mime_field = mailmime_field_new(type, NULL,
865 encoding, NULL, NULL, 0, NULL, NULL);
866 if (mime_field == NULL) {
867 mailmime_mechanism_free(encoding);
868 res = MAIL_ERROR_MEMORY;
869 goto free_list;
870 }
871
872 r = clist_append(list, mime_field);
873 if (r != 0) {
874 mailmime_field_free(mime_field);
875 res = MAIL_ERROR_MEMORY;
876 goto free_list;
877 }
878 }
879 }
880
881 if (imap_dsp != NULL) {
882 r = imap_disposition_to_mime_disposition(imap_dsp, &dsp);
883 if (r != MAIL_ERROR_PARSE) {
884 if (r != MAIL_NO_ERROR) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_list;
887 }
888
889 type = MAILMIME_FIELD_DISPOSITION;
890
891 mime_field = mailmime_field_new(type, NULL,
892 NULL, NULL, NULL, 0, dsp, NULL);
893 if (mime_field == NULL) {
894 mailmime_disposition_free(dsp);
895 res = MAIL_ERROR_MEMORY;
896 goto free_list;
897 }
898
899 r = clist_append(list, mime_field);
900 if (r != 0) {
901 mailmime_field_free(mime_field);
902 res = MAIL_ERROR_MEMORY;
903 goto free_list;
904 }
905 }
906 }
907
908 if (imap_lang != NULL) {
909 r = imap_language_to_mime_language(imap_lang, &lang);
910 if (r != MAIL_NO_ERROR) {
911 res = MAIL_ERROR_MEMORY;
912 goto free_list;
913 }
914
915 type = MAILMIME_FIELD_LANGUAGE;
916
917 mime_field = mailmime_field_new(type, NULL,
918 NULL, NULL, NULL, 0, NULL, lang);
919 if (mime_field == NULL) {
920 mailmime_language_free(lang);
921 res = MAIL_ERROR_MEMORY;
922 goto free_list;
923 }
924
925 r = clist_append(list, mime_field);
926 if (r != 0) {
927 mailmime_field_free(mime_field);
928 res = MAIL_ERROR_MEMORY;
929 goto free_list;
930 }
931 }
932
933 mime_fields = mailmime_fields_new(list);
934 if (mime_fields == NULL) {
935 res = MAIL_ERROR_MEMORY;
936 goto free_list;
937 }
938
939 * result = mime_fields;
940
941 return MAIL_NO_ERROR;
942
943 free_list:
944 clist_foreach(list, (clist_func) mailmime_fields_free, NULL);
945 clist_free(list);
946 err:
947 return res;
948}
949
950static int
951imap_body_type_basic_to_body(struct mailimap_body_type_basic *
952 imap_type_basic,
953 struct mailimap_body_ext_1part *
954 body_ext_1part,
955 struct mailmime ** result)
956{
957 struct mailmime_content * content;
958 struct mailmime_fields * mime_fields;
959 struct mailmime * body;
960 int r;
961 int res;
962 uint32_t mime_size;
963
964 r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic,
965 imap_type_basic->bd_fields->bd_parameter, &content);
966 if (r != MAIL_NO_ERROR) {
967 res = r;
968 goto err;
969 }
970
971 if (body_ext_1part != NULL)
972 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
973 body_ext_1part->bd_disposition,
974 body_ext_1part->bd_language,
975 &mime_fields, &mime_size);
976 else
977 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
978 NULL, NULL,
979 &mime_fields, &mime_size);
980 if (r != MAIL_NO_ERROR) {
981 res = r;
982 goto free_content;
983 }
984
985 body = mailmime_new(MAILMIME_SINGLE, NULL,
986 mime_size, mime_fields, content,
987 NULL, NULL, NULL, NULL, NULL, NULL);
988
989 if (body == NULL) {
990 res = MAIL_ERROR_MEMORY;
991 goto free_fields;
992 }
993
994 * result = body;
995
996 return MAIL_NO_ERROR;
997
998 free_fields:
999 mailmime_fields_free(mime_fields);
1000 free_content:
1001 mailmime_content_free(content);
1002 err:
1003 return res;
1004}
1005
1006static int
1007imap_body_type_text_to_body(struct mailimap_body_type_text *
1008 imap_type_text,
1009 struct mailimap_body_ext_1part *
1010 body_ext_1part,
1011 struct mailmime ** result)
1012{
1013 struct mailmime_content * content;
1014 struct mailmime_fields * mime_fields;
1015 struct mailmime * body;
1016 int r;
1017 int res;
1018 uint32_t mime_size;
1019
1020 r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text,
1021 imap_type_text->bd_fields->bd_parameter,
1022 &content);
1023 if (r != MAIL_NO_ERROR) {
1024 res = r;
1025 goto err;
1026 }
1027
1028 if (body_ext_1part == NULL) {
1029 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1030 NULL, NULL,
1031 &mime_fields, &mime_size);
1032 }
1033 else {
1034 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1035 body_ext_1part->bd_disposition,
1036 body_ext_1part->bd_language,
1037 &mime_fields, &mime_size);
1038 }
1039 if (r != MAIL_NO_ERROR) {
1040 res = r;
1041 goto free_content;
1042 }
1043
1044 body = mailmime_new(MAILMIME_SINGLE, NULL,
1045 mime_size, mime_fields, content,
1046 NULL, NULL, NULL, NULL, NULL, NULL);
1047
1048 if (body == NULL) {
1049 res = MAIL_ERROR_MEMORY;
1050 goto free_fields;
1051 }
1052
1053 * result = body;
1054
1055 return MAIL_NO_ERROR;
1056
1057 free_fields:
1058 mailmime_fields_free(mime_fields);
1059 free_content:
1060 mailmime_content_free(content);
1061 err:
1062 return res;
1063}
1064
1065static int
1066imap_body_parameter_to_content(struct mailimap_body_fld_param *
1067 body_parameter,
1068 char * subtype,
1069 struct mailmime_type * mime_type,
1070 struct mailmime_content ** result)
1071{
1072 clist * parameters;
1073 char * new_subtype;
1074 struct mailmime_content * content;
1075 int r;
1076 int res;
1077
1078 new_subtype = strdup(subtype);
1079 if (new_subtype == NULL) {
1080 res = MAIL_ERROR_MEMORY;
1081 goto err;
1082 }
1083
1084 parameters = clist_new();
1085 if (parameters == NULL) {
1086 res = MAIL_ERROR_MEMORY;
1087 goto free_subtype;
1088 }
1089
1090 if (body_parameter != NULL) {
1091 clistiter * cur;
1092
1093 for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ;
1094 cur = clist_next(cur)) {
1095 struct mailimap_single_body_fld_param * imap_param;
1096 struct mailmime_parameter * param;
1097 char * name;
1098 char * value;
1099
1100 imap_param = clist_content(cur);
1101 name = strdup(imap_param->pa_name);
1102 if (name == NULL) {
1103 res = MAIL_ERROR_MEMORY;
1104 goto free_parameters;
1105 }
1106
1107 value = strdup(imap_param->pa_value);
1108 if (value == NULL) {
1109 free(name);
1110 res = MAIL_ERROR_MEMORY;
1111 goto free_parameters;
1112 }
1113
1114 param = mailmime_parameter_new(name, value);
1115 if (param == NULL) {
1116 free(value);
1117 free(name);
1118 res = MAIL_ERROR_MEMORY;
1119 goto free_parameters;
1120 }
1121
1122 r = clist_append(parameters, param);
1123 if (r != 0) {
1124 mailmime_parameter_free(param);
1125 res = MAIL_ERROR_MEMORY;
1126 goto free_parameters;
1127 }
1128 }
1129 }
1130
1131 content = mailmime_content_new(mime_type, new_subtype, parameters);
1132 if (content == NULL) {
1133 res = MAIL_ERROR_MEMORY;
1134 goto free_parameters;
1135 }
1136
1137 * result = content;
1138
1139 return MAIL_NO_ERROR;
1140
1141 free_parameters:
1142 clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL);
1143 clist_free(parameters);
1144 free_subtype:
1145 free(new_subtype);
1146 err:
1147 return res;
1148}
1149
1150static int
1151imap_body_type_text_to_content_type(char * subtype,
1152 struct mailimap_body_fld_param *
1153 body_parameter,
1154 struct mailmime_content ** result)
1155{
1156 struct mailmime_content * content;
1157 struct mailmime_type * mime_type;
1158 struct mailmime_discrete_type * discrete_type;
1159 int r;
1160 int res;
1161
1162 discrete_type = NULL;
1163
1164 discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
1165 NULL);
1166 if (discrete_type == NULL) {
1167 res = MAIL_ERROR_MEMORY;
1168 goto err;
1169 }
1170
1171 mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE,
1172 discrete_type, NULL);
1173 if (mime_type == NULL) {
1174 mailmime_discrete_type_free(discrete_type);
1175 res = MAIL_ERROR_MEMORY;
1176 goto err;
1177 }
1178
1179 r = imap_body_parameter_to_content(body_parameter, subtype,
1180 mime_type, &content);
1181 if (r != MAIL_NO_ERROR) {
1182 res = r;
1183 goto free_type;
1184 }
1185
1186 * result = content;
1187
1188 return MAIL_NO_ERROR;
1189
1190 free_type:
1191 mailmime_type_free(mime_type);
1192 err:
1193 return res;
1194}
1195
1196
1197static int
1198imap_body_type_msg_to_body(struct mailimap_body_type_msg *
1199 imap_type_msg,
1200 struct mailimap_body_ext_1part *
1201 body_ext_1part,
1202 struct mailmime ** result)
1203{
1204 struct mailmime * body;
1205 struct mailmime * msg_body;
1206 struct mailmime_fields * mime_fields;
1207 struct mailmime_composite_type * composite_type;
1208 struct mailmime_type * mime_type;
1209 struct mailmime_content * content_type;
1210 struct mailimf_fields * fields;
1211 int r;
1212 int res;
1213 uint32_t mime_size;
1214
1215 r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields,
1216 body_ext_1part->bd_disposition, body_ext_1part->bd_language,
1217 &mime_fields, &mime_size);
1218 if (r != MAIL_NO_ERROR) {
1219 res = r;
1220 goto err;
1221 }
1222
1223 r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields);
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mime_fields;
1227 }
1228
1229 r = imap_body_to_body(imap_type_msg->bd_body, &msg_body);
1230 if (r != MAIL_NO_ERROR) {
1231 res = r;
1232 goto free_fields;
1233 }
1234
1235 composite_type =
1236 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE,
1237 NULL);
1238 if (composite_type == NULL) {
1239 res = MAIL_ERROR_MEMORY;
1240 goto free_fields;
1241 }
1242
1243 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1244 NULL, composite_type);
1245 if (mime_type == NULL) {
1246 mailmime_composite_type_free(composite_type);
1247 res = MAIL_ERROR_MEMORY;
1248 goto free_fields;
1249 }
1250
1251 r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter,
1252 "rfc822", mime_type, &content_type);
1253 if (r != MAIL_NO_ERROR) {
1254 mailmime_type_free(mime_type);
1255 res = MAIL_ERROR_MEMORY;
1256 goto free_fields;
1257 }
1258
1259 body = mailmime_new(MAILMIME_MESSAGE, NULL,
1260 mime_size, mime_fields, content_type,
1261 NULL, NULL, NULL, NULL, fields, msg_body);
1262
1263 if (body == NULL) {
1264 res = MAIL_ERROR_MEMORY;
1265 goto free_content;
1266 }
1267
1268 * result = body;
1269
1270 return MAIL_NO_ERROR;
1271
1272 free_content:
1273 mailmime_content_free(content_type);
1274 free_fields:
1275 mailimf_fields_free(fields);
1276 free_mime_fields:
1277 mailmime_fields_free(mime_fields);
1278 err:
1279 return res;
1280}
1281
1282
1283static int
1284imap_body_type_1part_to_body(struct mailimap_body_type_1part *
1285 type_1part,
1286 struct mailmime ** result)
1287{
1288 struct mailmime * body;
1289 int r;
1290 int res;
1291
1292 switch (type_1part->bd_type) {
1293 case MAILIMAP_BODY_TYPE_1PART_BASIC:
1294 r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic,
1295 type_1part->bd_ext_1part,
1296 &body);
1297 if (r != MAIL_NO_ERROR) {
1298 res = r;
1299 goto err;
1300 }
1301
1302 break;
1303 case MAILIMAP_BODY_TYPE_1PART_MSG:
1304 r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg,
1305 type_1part->bd_ext_1part,
1306 &body);
1307 if (r != MAIL_NO_ERROR) {
1308 res = r;
1309 goto err;
1310 }
1311
1312 break;
1313 case MAILIMAP_BODY_TYPE_1PART_TEXT:
1314 r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text,
1315 type_1part->bd_ext_1part,
1316 &body);
1317 if (r != MAIL_NO_ERROR) {
1318 res = r;
1319 goto err;
1320 }
1321
1322 break;
1323 }
1324
1325 * result = body;
1326
1327 return MAIL_NO_ERROR;
1328
1329 err:
1330 return res;
1331}
1332
1333static int
1334imap_body_type_mpart_to_body(struct mailimap_body_type_mpart *
1335 type_mpart,
1336 struct mailmime ** result)
1337{
1338 struct mailmime_fields * mime_fields;
1339 struct mailmime_composite_type * composite_type;
1340 struct mailmime_type * mime_type;
1341 struct mailmime_content * content_type;
1342 struct mailmime * body;
1343 clistiter * cur;
1344 clist * list;
1345 int r;
1346 int res;
1347 uint32_t mime_size;
1348
1349 r = imap_body_fields_to_mime_fields(NULL,
1350 type_mpart->bd_ext_mpart->bd_disposition,
1351 type_mpart->bd_ext_mpart->bd_language,
1352 &mime_fields, &mime_size);
1353 if (r != MAIL_NO_ERROR) {
1354 res = r;
1355 goto err;
1356 }
1357
1358 composite_type =
1359 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART,
1360 NULL);
1361 if (composite_type == NULL) {
1362 res = MAIL_ERROR_MEMORY;
1363 goto free_fields;
1364 }
1365
1366 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1367 NULL, composite_type);
1368 if (mime_type == NULL) {
1369 mailmime_composite_type_free(composite_type);
1370 res = MAIL_ERROR_MEMORY;
1371 goto free_fields;
1372 }
1373
1374 r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter,
1375 type_mpart->bd_media_subtype,
1376 mime_type, &content_type);
1377 if (r != MAIL_NO_ERROR) {
1378 mailmime_type_free(mime_type);
1379 res = r;
1380 goto free_fields;
1381 }
1382
1383 list = clist_new();
1384 if (list == NULL) {
1385 res = MAIL_ERROR_MEMORY;
1386 goto free_content;
1387 }
1388
1389 for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ;
1390 cur = clist_next(cur)) {
1391 struct mailimap_body * imap_body;
1392 struct mailmime * sub_body;
1393
1394 imap_body = clist_content(cur);
1395
1396 r = imap_body_to_body(imap_body, &sub_body);
1397 if (r != MAIL_NO_ERROR) {
1398 res = r;
1399 goto free_list;
1400 }
1401
1402 r = clist_append(list, sub_body);
1403 if (r != 0) {
1404 mailmime_free(sub_body);
1405 res = r;
1406 goto free_list;
1407 }
1408 }
1409
1410 body = mailmime_new(MAILMIME_MULTIPLE, NULL,
1411 mime_size, mime_fields, content_type,
1412 NULL, NULL, NULL, list, NULL, NULL);
1413
1414 if (body == NULL) {
1415 res = MAIL_ERROR_MEMORY;
1416 goto err;
1417 }
1418
1419 * result = body;
1420
1421 return MAIL_NO_ERROR;
1422
1423 free_list:
1424 clist_foreach(list, (clist_func) mailmime_free, NULL);
1425 clist_free(list);
1426 free_content:
1427 mailmime_content_free(content_type);
1428 free_fields:
1429 mailmime_fields_free(mime_fields);
1430 err:
1431 return res;
1432}
1433
1434
1435int imap_body_to_body(struct mailimap_body * imap_body,
1436 struct mailmime ** result)
1437{
1438 struct mailmime * body;
1439 int r;
1440 int res;
1441
1442 switch (imap_body->bd_type) {
1443 case MAILIMAP_BODY_1PART:
1444 r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body);
1445 if (r != MAIL_NO_ERROR) {
1446 res = r;
1447 goto err;
1448 }
1449 break;
1450 case MAILIMAP_BODY_MPART:
1451 r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body);
1452 if (r != MAIL_NO_ERROR) {
1453 res = r;
1454 goto err;
1455 }
1456 break;
1457 default:
1458 return MAIL_ERROR_INVAL;
1459 }
1460
1461 * result = body;
1462
1463 return MAIL_NO_ERROR;
1464
1465 err:
1466 return res;
1467}
1468
1469int imap_address_to_mailbox(struct mailimap_address * imap_addr,
1470 struct mailimf_mailbox ** result)
1471{
1472 char * dsp_name;
1473 char * addr;
1474 struct mailimf_mailbox * mb;
1475 int res;
1476
1477 if (imap_addr->ad_personal_name == NULL)
1478 dsp_name = NULL;
1479 else {
1480 dsp_name = strdup(imap_addr->ad_personal_name);
1481 if (dsp_name == NULL) {
1482 res = MAIL_ERROR_MEMORY;
1483 goto err;
1484 }
1485 }
1486
1487 if (imap_addr->ad_host_name == NULL) {
1488 addr = strdup(imap_addr->ad_mailbox_name);
1489 if (addr == NULL) {
1490 res = MAIL_ERROR_MEMORY;
1491 goto free_name;
1492 }
1493 }
1494 else {
1495 addr = malloc(strlen(imap_addr->ad_mailbox_name) +
1496 strlen(imap_addr->ad_host_name) + 2);
1497 if (addr == NULL) {
1498 res = MAIL_ERROR_MEMORY;
1499 goto free_name;
1500 }
1501 strcpy(addr, imap_addr->ad_mailbox_name);
1502 strcat(addr, "@");
1503 strcat(addr, imap_addr->ad_host_name);
1504 }
1505
1506 mb = mailimf_mailbox_new(dsp_name, addr);
1507 if (mb == NULL) {
1508 res = MAIL_ERROR_MEMORY;
1509 goto free_addr;
1510 }
1511
1512 * result = mb;
1513
1514 return MAIL_NO_ERROR;
1515
1516 free_addr:
1517 free(addr);
1518 free_name:
1519 free(dsp_name);
1520 err:
1521 return res;
1522}
1523
1524int imap_address_to_address(struct mailimap_address * imap_addr,
1525 struct mailimf_address ** result)
1526{
1527 struct mailimf_address * addr;
1528 struct mailimf_mailbox * mb;
1529 int r;
1530 int res;
1531
1532 r = imap_address_to_mailbox(imap_addr, &mb);
1533 if (r != MAIL_NO_ERROR) {
1534 res = r;
1535 goto err;
1536 }
1537
1538 addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
1539 if (addr == NULL) {
1540 res = MAIL_ERROR_MEMORY;
1541 goto free_mb;
1542 }
1543
1544 * result = addr;
1545
1546 return MAIL_NO_ERROR;
1547
1548 free_mb:
1549 mailimf_mailbox_free(mb);
1550 err:
1551 return res;
1552}
1553
1554int
1555imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list,
1556 struct mailimf_mailbox_list ** result)
1557{
1558 clistiter * cur;
1559 clist * list;
1560 struct mailimf_mailbox_list * mb_list;
1561 int r;
1562 int res;
1563
1564 list = clist_new();
1565 if (list == NULL) {
1566 res = MAIL_ERROR_MEMORY;
1567 goto err;
1568 }
1569
1570 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1571 cur = clist_next(cur)) {
1572 struct mailimap_address * imap_addr;
1573 struct mailimf_mailbox * mb;
1574
1575 imap_addr = clist_content(cur);
1576
1577 if (imap_addr->ad_mailbox_name == NULL)
1578 continue;
1579
1580 r = imap_address_to_mailbox(imap_addr, &mb);
1581 if (r != MAIL_NO_ERROR) {
1582 res = r;
1583 goto free_list;
1584 }
1585
1586 r = clist_append(list, mb);
1587 if (r != 0) {
1588 mailimf_mailbox_free(mb);
1589 res = MAIL_ERROR_MEMORY;
1590 goto free_list;
1591 }
1592 }
1593
1594 mb_list = mailimf_mailbox_list_new(list);
1595 if (mb_list == NULL) {
1596 res = MAIL_ERROR_MEMORY;
1597 goto free_list;
1598 }
1599
1600 * result = mb_list;
1601
1602 return MAIL_NO_ERROR;
1603
1604 free_list:
1605 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1606 clist_free(list);
1607 err:
1608 return MAIL_ERROR_MEMORY;
1609}
1610
1611
1612
1613/*
1614 at exit, imap_mb_list will fall on the last element of the group,
1615 where mailbox name will be NIL, so that imap_mailbox_list_to_address_list
1616 can continue
1617*/
1618
1619static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter,
1620 struct mailimf_group ** result)
1621{
1622 clistiter * imap_mailbox_listiter;
1623 clist * list;
1624 struct mailimf_group * group;
1625 struct mailimap_address * imap_addr;
1626 char * group_name;
1627 clistiter * cur;
1628 struct mailimf_mailbox_list * mb_list;
1629 int r;
1630 int res;
1631
1632 imap_mailbox_listiter = * iter;
1633
1634 imap_addr = clist_content(imap_mailbox_listiter);
1635 if (imap_addr->ad_mailbox_name == NULL) {
1636 res = MAIL_ERROR_INVAL;
1637 goto err;
1638 }
1639
1640 group_name = strdup(imap_addr->ad_mailbox_name);
1641 if (group_name == NULL) {
1642 res = MAIL_ERROR_MEMORY;
1643 goto err;
1644 }
1645
1646 list = clist_new();
1647 if (list == NULL) {
1648 res = MAIL_ERROR_MEMORY;
1649 goto free_group_name;
1650 }
1651
1652 for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ;
1653 cur = clist_next(cur)) {
1654 struct mailimf_mailbox * mb;
1655
1656 imap_addr = clist_content(cur);
1657
1658 if (imap_addr->ad_mailbox_name == NULL) {
1659 break;
1660 }
1661
1662 r = imap_address_to_mailbox(imap_addr, &mb);
1663 if (r != MAIL_NO_ERROR) {
1664 res = r;
1665 goto free_list;
1666 }
1667
1668 r = clist_append(list, mb);
1669 if (r != 0) {
1670 mailimf_mailbox_free(mb);
1671 res = MAIL_ERROR_MEMORY;
1672 goto free_list;
1673 }
1674 }
1675
1676 mb_list = mailimf_mailbox_list_new(list);
1677 if (mb_list == NULL) {
1678 res = MAIL_ERROR_MEMORY;
1679 goto free_list;
1680 }
1681
1682 group = mailimf_group_new(group_name, mb_list);
1683 if (group == NULL) {
1684 mailimf_mailbox_list_free(mb_list);
1685 res = MAIL_ERROR_MEMORY;
1686 goto free_group_name;
1687 }
1688
1689 * result = group;
1690 * iter = cur;
1691
1692 return MAIL_NO_ERROR;
1693
1694 free_list:
1695 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1696 clist_free(list);
1697 free_group_name:
1698 free(group_name);
1699 err:
1700 return res;
1701}
1702
1703int
1704imap_mailbox_list_to_address_list(clist * imap_mailbox_list,
1705 struct mailimf_address_list ** result)
1706{
1707 clistiter * cur;
1708 clist * list;
1709 struct mailimf_address_list * addr_list;
1710 int r;
1711 int res;
1712
1713 list = clist_new();
1714 if (list == NULL) {
1715 res = MAIL_ERROR_MEMORY;
1716 goto err;
1717 }
1718
1719 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1720 cur = clist_next(cur)) {
1721 struct mailimap_address * imap_addr;
1722 struct mailimf_address * addr;
1723
1724 imap_addr = clist_content(cur);
1725
1726 if (imap_addr->ad_mailbox_name == NULL)
1727 continue;
1728
1729 if ((imap_addr->ad_host_name == NULL) &&
1730 (imap_addr->ad_mailbox_name != NULL)) {
1731 struct mailimf_group * group;
1732
1733 r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group);
1734 if (r != MAIL_NO_ERROR) {
1735 res = r;
1736 goto free_list;
1737 }
1738
1739 addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group);
1740 if (addr == NULL) {
1741 mailimf_group_free(group);
1742 res = MAIL_ERROR_MEMORY;
1743 goto free_list;
1744 }
1745 }
1746 else {
1747 r = imap_address_to_address(imap_addr, &addr);
1748 if (r != MAIL_NO_ERROR) {
1749 res = r;
1750 goto free_list;
1751 }
1752 }
1753
1754 r = clist_append(list, addr);
1755 if (r != 0) {
1756 mailimf_address_free(addr);
1757 res = MAIL_ERROR_MEMORY;
1758 goto free_list;
1759 }
1760 }
1761
1762 addr_list = mailimf_address_list_new(list);
1763 if (addr_list == NULL) {
1764 res = MAIL_ERROR_MEMORY;
1765 goto free_list;
1766 }
1767
1768 * result = addr_list;
1769
1770 return MAIL_NO_ERROR;
1771
1772 free_list:
1773 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1774 clist_free(list);
1775 err:
1776 return res;
1777}
1778
1779
1780int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1781{
1782 struct mailimap_fetch_att * fetch_att;
1783 int res;
1784 int r;
1785 char * header;
1786 clist * hdrlist;
1787 struct mailimap_header_list * imap_hdrlist;
1788 struct mailimap_section * section;
1789
1790 fetch_att = mailimap_fetch_att_new_envelope();
1791 if (fetch_att == NULL) {
1792 res = MAIL_ERROR_MEMORY;
1793 goto err;
1794 }
1795
1796 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1797 if (r != MAILIMAP_NO_ERROR) {
1798 mailimap_fetch_att_free(fetch_att);
1799 res = MAIL_ERROR_MEMORY;
1800 goto err;
1801 }
1802
1803 header = strdup("References");
1804 if (header == NULL) {
1805 mailimap_fetch_att_free(fetch_att);
1806 res = MAIL_ERROR_MEMORY;
1807 goto err;
1808 }
1809
1810 hdrlist = clist_new();
1811 if (hdrlist == NULL) {
1812 free(header);
1813 mailimap_fetch_att_free(fetch_att);
1814 res = MAIL_ERROR_MEMORY;
1815 goto err;
1816 }
1817
1818 r = clist_append(hdrlist, header);
1819 if (r < 0) {
1820 free(header);
1821 clist_foreach(hdrlist, (clist_func) free, NULL);
1822 clist_free(hdrlist);
1823 mailimap_fetch_att_free(fetch_att);
1824 res = MAIL_ERROR_MEMORY;
1825 goto err;
1826 }
1827
1828 imap_hdrlist = mailimap_header_list_new(hdrlist);
1829 if (imap_hdrlist == 0) {
1830 clist_foreach(hdrlist, (clist_func) free, NULL);
1831 clist_free(hdrlist);
1832 mailimap_fetch_att_free(fetch_att);
1833 res = MAIL_ERROR_MEMORY;
1834 goto err;
1835 }
1836
1837 section = mailimap_section_new_header_fields(imap_hdrlist);
1838 if (section == NULL) {
1839 mailimap_header_list_free(imap_hdrlist);
1840 mailimap_fetch_att_free(fetch_att);
1841 res = MAIL_ERROR_MEMORY;
1842 goto err;
1843 }
1844
1845 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1846 if (fetch_att == NULL) {
1847 mailimap_section_free(section);
1848 res = MAIL_ERROR_MEMORY;
1849 goto err;
1850 }
1851
1852 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1853 if (r != MAILIMAP_NO_ERROR) {
1854 mailimap_fetch_att_free(fetch_att);
1855 res = MAIL_ERROR_MEMORY;
1856 goto err;
1857 }
1858
1859 return MAIL_NO_ERROR;
1860
1861 err:
1862 return res;
1863}
1864
1865
1866int imap_env_to_fields(struct mailimap_envelope * env,
1867 char * ref_str, size_t ref_size,
1868 struct mailimf_fields ** result)
1869{
1870 clist * list;
1871 struct mailimf_field * field;
1872 int r;
1873 struct mailimf_fields * fields;
1874 int res;
1875
1876 list = clist_new();
1877 if (list == NULL) {
1878 res = MAIL_ERROR_MEMORY;
1879 goto err;
1880 }
1881
1882 if (env->env_date != NULL) {
1883 size_t cur_token;
1884 struct mailimf_date_time * date_time;
1885
1886 cur_token = 0;
1887 r = mailimf_date_time_parse(env->env_date, strlen(env->env_date),
1888 &cur_token, &date_time);
1889
1890 if (r == MAILIMF_NO_ERROR) {
1891 struct mailimf_orig_date * orig;
1892
1893 orig = mailimf_orig_date_new(date_time);
1894 if (orig == NULL) {
1895 mailimf_date_time_free(date_time);
1896 res = MAIL_ERROR_MEMORY;
1897 goto free_list;
1898 }
1899
1900 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
1901 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1902 NULL, orig, NULL,
1903 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1904 NULL, NULL, NULL, NULL, NULL);
1905 if (field == NULL) {
1906 mailimf_orig_date_free(orig);
1907 res = MAIL_ERROR_MEMORY;
1908 goto free_list;
1909 }
1910
1911 r = clist_append(list, field);
1912 if (r != 0) {
1913 mailimf_field_free(field);
1914 res = MAIL_ERROR_MEMORY;
1915 goto free_list;
1916 }
1917 }
1918 }
1919
1920 if (env->env_subject != NULL) {
1921 char * subject;
1922 struct mailimf_subject * subject_field;
1923
1924 subject = strdup(env->env_subject);
1925 if (subject == NULL) {
1926 res = MAIL_ERROR_MEMORY;
1927 goto free_list;
1928 }
1929
1930
1931 subject_field = mailimf_subject_new(subject);
1932 if (subject_field == NULL) {
1933 free(subject);
1934 res = MAIL_ERROR_MEMORY;
1935 goto free_list;
1936 }
1937
1938 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1939 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1940 NULL, NULL, NULL,
1941 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1942 NULL, subject_field, NULL, NULL, NULL);
1943 if (field == NULL) {
1944 mailimf_subject_free(subject_field);
1945 res = MAIL_ERROR_MEMORY;
1946 goto free_list;
1947 }
1948
1949 r = clist_append(list, field);
1950 if (r != 0) {
1951 mailimf_field_free(field);
1952 res = MAIL_ERROR_MEMORY;
1953 goto free_list;
1954 }
1955 }
1956
1957 if (env->env_from != NULL) {
1958 if (env->env_from->frm_list != NULL) {
1959 struct mailimf_mailbox_list * mb_list;
1960 struct mailimf_from * from;
1961
1962 r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list);
1963
1964 if (r != MAIL_NO_ERROR) {
1965 res = r;
1966 goto free_list;
1967 }
1968
1969 from = mailimf_from_new(mb_list);
1970 if (from == NULL) {
1971 mailimf_mailbox_list_free(mb_list);
1972 res = MAIL_ERROR_MEMORY;
1973 goto free_list;
1974 }
1975
1976 field = mailimf_field_new(MAILIMF_FIELD_FROM,
1977 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1978 NULL, NULL, from,
1979 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1980 NULL, NULL, NULL, NULL, NULL);
1981 if (field == NULL) {
1982 mailimf_from_free(from);
1983 res = MAIL_ERROR_MEMORY;
1984 goto free_list;
1985 }
1986
1987 r = clist_append(list, field);
1988 if (r != 0) {
1989 mailimf_field_free(field);
1990 res = MAIL_ERROR_MEMORY;
1991 goto free_list;
1992 }
1993 }
1994 }
1995
1996 if (env->env_sender != NULL) {
1997 if (env->env_sender->snd_list != NULL) {
1998 struct mailimf_sender * sender;
1999 struct mailimf_mailbox * mb;
2000
2001 r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb);
2002
2003 if (r != MAIL_NO_ERROR) {
2004 res = r;
2005 goto free_list;
2006 }
2007
2008 sender = mailimf_sender_new(mb);
2009 if (sender == NULL) {
2010 mailimf_mailbox_free(mb);
2011 res = MAIL_ERROR_MEMORY;
2012 goto free_list;
2013 }
2014
2015 field = mailimf_field_new(MAILIMF_FIELD_SENDER,
2016 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2017 NULL, NULL, NULL,
2018 sender, NULL, NULL, NULL, NULL, NULL, NULL,
2019 NULL, NULL, NULL, NULL, NULL);
2020 if (field == NULL) {
2021 mailimf_sender_free(sender);
2022 res = MAIL_ERROR_MEMORY;
2023 goto free_list;
2024 }
2025
2026 r = clist_append(list, field);
2027 if (r != 0) {
2028 mailimf_field_free(field);
2029 res = MAIL_ERROR_MEMORY;
2030 goto free_list;
2031 }
2032 }
2033 }
2034
2035 if (env->env_reply_to != NULL) {
2036 if (env->env_reply_to->rt_list != NULL) {
2037 struct mailimf_address_list * addr_list;
2038 struct mailimf_reply_to * reply_to;
2039
2040 r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list,
2041 &addr_list);
2042
2043 if (r != MAIL_NO_ERROR) {
2044 res = r;
2045 goto free_list;
2046 }
2047
2048 reply_to = mailimf_reply_to_new(addr_list);
2049 if (reply_to == NULL) {
2050 mailimf_address_list_free(addr_list);
2051 res = MAIL_ERROR_MEMORY;
2052 goto free_list;
2053 }
2054
2055 field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
2056 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2057 NULL, NULL, NULL,
2058 NULL, reply_to, NULL, NULL, NULL, NULL, NULL,
2059 NULL, NULL, NULL, NULL, NULL);
2060 if (field == NULL) {
2061 mailimf_reply_to_free(reply_to);
2062 res = MAIL_ERROR_MEMORY;
2063 goto free_list;
2064 }
2065
2066 r = clist_append(list, field);
2067 if (r != 0) {
2068 mailimf_field_free(field);
2069 res = MAIL_ERROR_MEMORY;
2070 goto free_list;
2071 }
2072 }
2073 }
2074
2075 if (env->env_to != NULL) {
2076 if (env->env_to->to_list != NULL) {
2077 struct mailimf_address_list * addr_list;
2078 struct mailimf_to * to;
2079
2080 r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list);
2081
2082 if (r != MAIL_NO_ERROR) {
2083 res = r;
2084 goto free_list;
2085 }
2086
2087 to = mailimf_to_new(addr_list);
2088 if (to == NULL) {
2089 mailimf_address_list_free(addr_list);
2090 res = MAIL_ERROR_MEMORY;
2091 goto free_list;
2092 }
2093
2094 field = mailimf_field_new(MAILIMF_FIELD_TO,
2095 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2096 NULL, NULL, NULL,
2097 NULL, NULL, to, NULL, NULL, NULL, NULL,
2098 NULL, NULL, NULL, NULL, NULL);
2099 if (field == NULL) {
2100 mailimf_to_free(to);
2101 res = MAIL_ERROR_MEMORY;
2102 goto free_list;
2103 }
2104
2105 r = clist_append(list, field);
2106 if (r != 0) {
2107 mailimf_field_free(field);
2108 res = MAIL_ERROR_MEMORY;
2109 goto free_list;
2110 }
2111 }
2112 }
2113
2114 if (env->env_cc != NULL) {
2115 if (env->env_cc->cc_list != NULL) {
2116 struct mailimf_address_list * addr_list;
2117 struct mailimf_cc * cc;
2118
2119 r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list);
2120
2121 if (r != MAIL_NO_ERROR) {
2122 res = r;
2123 goto free_list;
2124 }
2125
2126 cc = mailimf_cc_new(addr_list);
2127 if (cc == NULL) {
2128 mailimf_address_list_free(addr_list);
2129 res = MAIL_ERROR_MEMORY;
2130 goto free_list;
2131 }
2132
2133 field = mailimf_field_new(MAILIMF_FIELD_CC,
2134 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2135 NULL, NULL, NULL,
2136 NULL, NULL, NULL, cc, NULL, NULL, NULL,
2137 NULL, NULL, NULL, NULL, NULL);
2138 if (field == NULL) {
2139 mailimf_cc_free(cc);
2140 res = MAIL_ERROR_MEMORY;
2141 goto free_list;
2142 }
2143
2144 r = clist_append(list, field);
2145 if (r != 0) {
2146 mailimf_field_free(field);
2147 res = MAIL_ERROR_MEMORY;
2148 goto free_list;
2149 }
2150 }
2151 }
2152
2153 if (env->env_bcc != NULL) {
2154 if (env->env_bcc->bcc_list != NULL) {
2155 struct mailimf_address_list * addr_list;
2156 struct mailimf_bcc * bcc;
2157
2158 r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list,
2159 &addr_list);
2160
2161 if (r != MAIL_NO_ERROR) {
2162 res = r;
2163 goto free_list;
2164 }
2165
2166 bcc = mailimf_bcc_new(addr_list);
2167 if (bcc == NULL) {
2168 mailimf_address_list_free(addr_list);
2169 res = MAIL_ERROR_MEMORY;
2170 goto free_list;
2171 }
2172
2173 field = mailimf_field_new(MAILIMF_FIELD_BCC,
2174 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2175 NULL, NULL, NULL,
2176 NULL, NULL, NULL, NULL, bcc, NULL, NULL,
2177 NULL, NULL, NULL, NULL, NULL);
2178 if (field == NULL) {
2179 mailimf_bcc_free(bcc);
2180 res = MAIL_ERROR_MEMORY;
2181 goto free_list;
2182 }
2183
2184 r = clist_append(list, field);
2185 if (r != 0) {
2186 mailimf_field_free(field);
2187 res = MAIL_ERROR_MEMORY;
2188 goto free_list;
2189 }
2190 }
2191 }
2192
2193 if (env->env_in_reply_to != NULL) {
2194 struct mailimf_in_reply_to * in_reply_to;
2195 size_t cur_token;
2196 clist * msg_id_list;
2197
2198 cur_token = 0;
2199 r = mailimf_msg_id_list_parse(env->env_in_reply_to,
2200 strlen(env->env_in_reply_to), &cur_token, &msg_id_list);
2201
2202 switch (r) {
2203 case MAILIMF_NO_ERROR:
2204 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
2205 if (in_reply_to == NULL) {
2206 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
2207 clist_free(msg_id_list);
2208 res = MAIL_ERROR_MEMORY;
2209 goto free_list;
2210 }
2211
2212 field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
2213 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2214 NULL, NULL, NULL,
2215 NULL, NULL, NULL, NULL, NULL, NULL,
2216 in_reply_to,
2217 NULL, NULL, NULL, NULL, NULL);
2218 if (field == NULL) {
2219 mailimf_in_reply_to_free(in_reply_to);
2220 res = MAIL_ERROR_MEMORY;
2221 goto free_list;
2222 }
2223
2224 r = clist_append(list, field);
2225 if (r != 0) {
2226 mailimf_field_free(field);
2227 res = MAIL_ERROR_MEMORY;
2228 goto free_list;
2229 }
2230 break;
2231
2232 case MAILIMF_ERROR_PARSE:
2233 break;
2234
2235 default:
2236 res = maildriver_imf_error_to_mail_error(r);
2237 goto free_list;
2238 }
2239 }
2240
2241 if (env->env_message_id != NULL) {
2242 char * id;
2243 struct mailimf_message_id * msg_id;
2244 size_t cur_token;
2245
2246 cur_token = 0;
2247 r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id),
2248 &cur_token, &id);
2249 switch (r) {
2250 case MAILIMF_NO_ERROR:
2251
2252 msg_id = mailimf_message_id_new(id);
2253 if (msg_id == NULL) {
2254 mailimf_msg_id_free(id);
2255 res = MAIL_ERROR_MEMORY;
2256 goto free_list;
2257 }
2258
2259 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
2260 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2261 NULL, NULL, NULL,
2262 NULL, NULL, NULL, NULL, NULL, msg_id, NULL,
2263 NULL, NULL, NULL, NULL, NULL);
2264 if (field == NULL) {
2265 mailimf_message_id_free(msg_id);
2266 res = MAIL_ERROR_MEMORY;
2267 goto free_list;
2268 }
2269
2270 r = clist_append(list, field);
2271 if (r != 0) {
2272 mailimf_field_free(field);
2273 res = MAIL_ERROR_MEMORY;
2274 goto free_list;
2275 }
2276 break;
2277
2278 case MAILIMF_ERROR_PARSE:
2279 break;
2280
2281 default:
2282 res = maildriver_imf_error_to_mail_error(r);
2283 goto free_list;
2284 }
2285 }
2286
2287 if (ref_str != NULL) {
2288 struct mailimf_references * references;
2289 size_t cur_token;
2290
2291 cur_token = 0;
2292 r = mailimf_references_parse(ref_str, ref_size,
2293 &cur_token, &references);
2294 switch (r) {
2295 case MAILIMF_NO_ERROR:
2296 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
2297 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2298 NULL, NULL, NULL,
2299 NULL, NULL, NULL, NULL, NULL, NULL,
2300 NULL,
2301 references, NULL, NULL, NULL, NULL);
2302 if (field == NULL) {
2303 mailimf_references_free(references);
2304 res = MAIL_ERROR_MEMORY;
2305 goto free_list;
2306 }
2307
2308 r = clist_append(list, field);
2309 if (r < 0) {
2310 mailimf_field_free(field);
2311 res = MAIL_ERROR_MEMORY;
2312 goto free_list;
2313 }
2314 break;
2315
2316 case MAILIMF_ERROR_PARSE:
2317 break;
2318
2319 default:
2320 res = maildriver_imf_error_to_mail_error(r);
2321 goto free_list;
2322 }
2323 }
2324
2325 fields = mailimf_fields_new(list);
2326 if (fields == NULL) {
2327 res = MAIL_ERROR_MEMORY;
2328 goto free_list;
2329 }
2330
2331 * result = fields;
2332
2333 return MAIL_NO_ERROR;
2334
2335 free_list:
2336 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
2337 clist_free(list);
2338 err:
2339 return res;
2340}
2341
2342int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
2343 uint32_t * puid,
2344 struct mailimap_envelope ** pimap_envelope,
2345 char ** preferences,
2346 size_t * pref_size,
2347 struct mailimap_msg_att_dynamic ** patt_dyn,
2348 struct mailimap_body ** pimap_body)
2349{
2350 clistiter * item_cur;
2351 uint32_t uid;
2352 struct mailimap_envelope * imap_envelope;
2353 char * references;
2354 size_t ref_size;
2355 struct mailimap_msg_att_dynamic * att_dyn;
2356 struct mailimap_body * imap_body;
2357
2358 uid = 0;
2359 imap_envelope = NULL;
2360 references = NULL;
2361 ref_size = 0;
2362 att_dyn = NULL;
2363 imap_body = NULL;
2364
2365 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2366 item_cur = clist_next(item_cur)) {
2367 struct mailimap_msg_att_item * item;
2368
2369 item = clist_content(item_cur);
2370
2371 switch (item->att_type) {
2372 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2373 switch (item->att_data.att_static->att_type) {
2374 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
2375 if (imap_body == NULL)
2376 imap_body = item->att_data.att_static->att_data.att_bodystructure;
2377 break;
2378
2379 case MAILIMAP_MSG_ATT_ENVELOPE:
2380 if (imap_envelope == NULL) {
2381 imap_envelope = item->att_data.att_static->att_data.att_env;
2382 }
2383 break;
2384
2385 case MAILIMAP_MSG_ATT_UID:
2386 uid = item->att_data.att_static->att_data.att_uid;
2387 break;
2388
2389 case MAILIMAP_MSG_ATT_BODY_SECTION:
2390 if (references == NULL) {
2391 references = item->att_data.att_static->att_data.att_body_section->sec_body_part;
2392 ref_size = item->att_data.att_static->att_data.att_body_section->sec_length;
2393 }
2394 break;
2395 }
2396 break;
2397
2398 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
2399 if (att_dyn == NULL) {
2400 att_dyn = item->att_data.att_dyn;
2401 }
2402 break;
2403 }
2404 }
2405
2406 if (puid != NULL)
2407 * puid = uid;
2408 if (pimap_envelope != NULL)
2409 * pimap_envelope = imap_envelope;
2410 if (preferences != NULL)
2411 * preferences = references;
2412 if (pref_size != NULL)
2413 * pref_size = ref_size;
2414 if (patt_dyn != NULL)
2415 * patt_dyn = att_dyn;
2416 if (pimap_body != NULL)
2417 * pimap_body = imap_body;
2418
2419 return MAIL_NO_ERROR;
2420}
2421
2422int
2423imap_fetch_result_to_envelop_list(clist * fetch_result,
2424 struct mailmessage_list * env_list)
2425{
2426 clistiter * cur;
2427 int r;
2428 unsigned int i;
2429
2430 i = 0;
2431
2432 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2433 cur = clist_next(cur)) {
2434 struct mailimap_msg_att * msg_att;
2435 uint32_t uid;
2436 struct mailimap_envelope * imap_envelope;
2437 struct mailimap_msg_att_dynamic * att_dyn;
2438 char * references;
2439 size_t ref_size;
2440
2441 msg_att = clist_content(cur);
2442
2443 r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope,
2444 &references, &ref_size,
2445 &att_dyn,
2446 NULL);
2447
2448 if (r == MAIL_NO_ERROR) {
2449 if (uid != 0) {
2450 while (i < carray_count(env_list->msg_tab)) {
2451 mailmessage * msg;
2452
2453 msg = carray_get(env_list->msg_tab, i);
2454
2455 if (uid == msg->msg_index) {
2456 struct mailimf_fields * fields;
2457 struct mail_flags * flags;
2458
2459 if (imap_envelope != NULL) {
2460 r = imap_env_to_fields(imap_envelope,
2461 references, ref_size, &fields);
2462 if (r == MAIL_NO_ERROR) {
2463 msg->msg_fields = fields;
2464 }
2465 }
2466
2467 if (att_dyn != NULL) {
2468 r = imap_flags_to_flags(att_dyn, &flags);
2469
2470 if (r == MAIL_NO_ERROR) {
2471 msg->msg_flags = flags;
2472 }
2473 }
2474
2475 i ++;
2476 break;
2477 }
2478
2479 i ++;
2480 }
2481 }
2482 }
2483 }
2484
2485 return MAIL_NO_ERROR;
2486}
2487
2488
2489int mailimf_date_time_to_imap_date(struct mailimf_date_time * date,
2490 struct mailimap_date ** result)
2491{
2492 struct mailimap_date * imap_date;
2493
2494 imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year);
2495 if (imap_date == NULL)
2496 return MAIL_ERROR_MEMORY;
2497
2498 * result = imap_date;
2499
2500 return MAIL_NO_ERROR;
2501}
2502
2503
2504#if 0
2505int mail_search_to_imap_search(struct mail_search_key * key,
2506 struct mailimap_search_key ** result)
2507{
2508 struct mailimap_search_key * imap_key;
2509
2510 char * bcc;
2511 struct mailimap_date * before;
2512 char * body;
2513 char * cc;
2514 char * from;
2515 struct mailimap_date * on;
2516 struct mailimap_date * since;
2517 char * subject;
2518 char * text;
2519 char * to;
2520 char * header_name;
2521 char * header_value;
2522 size_t larger;
2523 struct mailimap_search_key * not;
2524 struct mailimap_search_key * or1;
2525 struct mailimap_search_key * or2;
2526 size_t smaller;
2527 clist * multiple;
2528 int type;
2529 clistiter * cur;
2530 int r;
2531 int res;
2532
2533 bcc = NULL;
2534 before = NULL;
2535 body = NULL;
2536 cc = NULL;
2537 from = NULL;
2538 on = NULL;
2539 since = NULL;
2540 subject = NULL;
2541 text = NULL;
2542 to = NULL;
2543 header_name = NULL;
2544 header_value = NULL;
2545 not = NULL;
2546 or1 = NULL;
2547 or2 = NULL;
2548 multiple = NULL;
2549 larger = 0;
2550 smaller = 0;
2551
2552 switch (key->sk_type) {
2553 case MAIL_SEARCH_KEY_ALL:
2554 type = MAILIMAP_SEARCH_KEY_ALL;
2555 break;
2556
2557 case MAIL_SEARCH_KEY_ANSWERED:
2558 type = MAILIMAP_SEARCH_KEY_ANSWERED;
2559 break;
2560
2561 case MAIL_SEARCH_KEY_BCC:
2562 type = MAILIMAP_SEARCH_KEY_BCC;
2563 bcc = strdup(key->sk_bcc);
2564 if (bcc == NULL) {
2565 res = MAIL_ERROR_MEMORY;
2566 goto err;
2567 }
2568 break;
2569
2570 case MAIL_SEARCH_KEY_BEFORE:
2571 type = MAILIMAP_SEARCH_KEY_BEFORE;
2572 r = mailimf_date_time_to_imap_date(key->sk_before, &before);
2573 if (r != MAIL_NO_ERROR) {
2574 res = r;
2575 goto err;
2576 }
2577 break;
2578
2579 case MAIL_SEARCH_KEY_BODY:
2580 type = MAILIMAP_SEARCH_KEY_BODY;
2581 body = strdup(key->sk_body);
2582 if (body == NULL) {
2583 res = MAIL_ERROR_MEMORY;
2584 goto err;
2585 }
2586 break;
2587
2588 case MAIL_SEARCH_KEY_CC:
2589 type = MAILIMAP_SEARCH_KEY_CC;
2590 cc = strdup(key->sk_cc);
2591 if (cc == NULL) {
2592 res = MAIL_ERROR_MEMORY;
2593 goto err;
2594 }
2595 break;
2596
2597 case MAIL_SEARCH_KEY_DELETED:
2598 type = MAILIMAP_SEARCH_KEY_DELETED;
2599 break;
2600
2601 case MAIL_SEARCH_KEY_FLAGGED:
2602 type = MAILIMAP_SEARCH_KEY_FLAGGED;
2603 break;
2604
2605 case MAIL_SEARCH_KEY_FROM:
2606 type = MAILIMAP_SEARCH_KEY_FROM;
2607 from = strdup(key->sk_from);
2608 if (from == NULL) {
2609 res = MAIL_ERROR_MEMORY;
2610 goto err;
2611 }
2612 break;
2613
2614 case MAIL_SEARCH_KEY_NEW:
2615 type = MAILIMAP_SEARCH_KEY_NEW;
2616 break;
2617
2618 case MAIL_SEARCH_KEY_OLD:
2619 type = MAILIMAP_SEARCH_KEY_OLD;
2620 break;
2621
2622 case MAIL_SEARCH_KEY_ON:
2623 type = MAILIMAP_SEARCH_KEY_ON;
2624 r = mailimf_date_time_to_imap_date(key->sk_on, &on);
2625 if (r != MAIL_NO_ERROR) {
2626 res = r;
2627 goto err;
2628 }
2629 break;
2630
2631 case MAIL_SEARCH_KEY_RECENT:
2632 type = MAILIMAP_SEARCH_KEY_RECENT;
2633 break;
2634
2635 case MAIL_SEARCH_KEY_SEEN:
2636 type = MAILIMAP_SEARCH_KEY_SEEN;
2637 break;
2638
2639 case MAIL_SEARCH_KEY_SINCE:
2640 type = MAILIMAP_SEARCH_KEY_SINCE;
2641 r = mailimf_date_time_to_imap_date(key->sk_since, &since);
2642 if (r != MAIL_NO_ERROR) {
2643 res = r;
2644 goto err;
2645 }
2646 break;
2647
2648 case MAIL_SEARCH_KEY_SUBJECT:
2649 type = MAILIMAP_SEARCH_KEY_SUBJECT;
2650 subject = strdup(key->sk_subject);
2651 if (subject == NULL) {
2652 res = MAIL_ERROR_MEMORY;
2653 goto err;
2654 }
2655 break;
2656
2657 case MAIL_SEARCH_KEY_TEXT:
2658 type = MAILIMAP_SEARCH_KEY_TEXT;
2659 text = strdup(key->sk_text);
2660 if (text == NULL) {
2661 res = MAIL_ERROR_MEMORY;
2662 goto err;
2663 }
2664 break;
2665
2666 case MAIL_SEARCH_KEY_TO:
2667 type = MAILIMAP_SEARCH_KEY_TO;
2668 to = strdup(key->sk_to);
2669 if (to == NULL) {
2670 return MAIL_ERROR_MEMORY;
2671 goto err;
2672 }
2673 break;
2674
2675 case MAIL_SEARCH_KEY_UNANSWERED:
2676 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2677 break;
2678
2679 case MAIL_SEARCH_KEY_UNDELETED:
2680 type = MAILIMAP_SEARCH_KEY_UNFLAGGED;
2681 break;
2682
2683 case MAIL_SEARCH_KEY_UNFLAGGED:
2684 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2685 break;
2686
2687 case MAIL_SEARCH_KEY_UNSEEN:
2688 type = MAILIMAP_SEARCH_KEY_UNSEEN;
2689 break;
2690
2691 case MAIL_SEARCH_KEY_HEADER:
2692 type = MAILIMAP_SEARCH_KEY_HEADER;
2693 header_name = strdup(key->sk_header_name);
2694 if (header_name == NULL) {
2695 res = MAIL_ERROR_MEMORY;
2696 goto err;
2697 }
2698 header_value = strdup(key->sk_header_value);
2699 if (header_value == NULL) {
2700 free(header_name);
2701 res = MAIL_ERROR_MEMORY;
2702 goto err;
2703 }
2704 break;
2705
2706 case MAIL_SEARCH_KEY_LARGER:
2707 type = MAILIMAP_SEARCH_KEY_LARGER;
2708 larger = key->sk_larger;
2709 break;
2710
2711 case MAIL_SEARCH_KEY_NOT:
2712 type = MAILIMAP_SEARCH_KEY_NOT;
2713 r = mail_search_to_imap_search(key->sk_not, &not);
2714 if (r != MAIL_NO_ERROR) {
2715 res = r;
2716 goto err;
2717 }
2718 break;
2719
2720 case MAIL_SEARCH_KEY_OR:
2721 type = MAILIMAP_SEARCH_KEY_OR;
2722 r = mail_search_to_imap_search(key->sk_or1, &or1);
2723 if (r != MAIL_NO_ERROR) {
2724 res = r;
2725 goto err;
2726 }
2727 r = mail_search_to_imap_search(key->sk_or2, &or2);
2728 if (r != MAIL_NO_ERROR) {
2729 mailimap_search_key_free(or1);
2730 res = r;
2731 goto err;
2732 }
2733 break;
2734
2735 case MAIL_SEARCH_KEY_SMALLER:
2736 type = MAILIMAP_SEARCH_KEY_SMALLER;
2737 smaller = key->sk_smaller;
2738 break;
2739
2740 case MAIL_SEARCH_KEY_MULTIPLE:
2741 multiple = clist_new();
2742 if (multiple == NULL) {
2743 res = MAIL_ERROR_MEMORY;
2744 goto err;
2745 }
2746
2747 type = MAILIMAP_SEARCH_KEY_MULTIPLE;
2748 for(cur = clist_begin(key->sk_multiple) ; cur != NULL ;
2749 cur = clist_next(cur)) {
2750 struct mail_search_key * key_elt;
2751 struct mailimap_search_key * imap_key_elt;
2752
2753 key_elt = clist_content(cur);
2754 r = mail_search_to_imap_search(key_elt, &imap_key_elt);
2755 if (r != MAIL_NO_ERROR) {
2756 res = r;
2757 goto free_list;
2758 }
2759
2760 r = clist_append(multiple, imap_key_elt);
2761 if (r != 0) {
2762 mailimap_search_key_free(imap_key_elt);
2763 res = MAIL_ERROR_MEMORY;
2764 goto free_list;
2765 }
2766 }
2767 break;
2768
2769 free_list:
2770 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2771 clist_free(multiple);
2772 goto err;
2773
2774 default:
2775 return MAIL_ERROR_INVAL;
2776 }
2777
2778 imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from,
2779 NULL, on, since, subject, text,
2780 to, NULL, header_name,
2781 header_value, larger, not, or1, or2,
2782 NULL, NULL, NULL, smaller, NULL,
2783 NULL, multiple);
2784 if (imap_key == NULL) {
2785 res = MAIL_ERROR_MEMORY;
2786 goto free;
2787 }
2788
2789 * result = imap_key;
2790
2791 return MAIL_NO_ERROR;
2792
2793 free:
2794 if (bcc != NULL)
2795 free(bcc);
2796 if (before != NULL)
2797 mailimap_date_free(before);
2798 if (body != NULL)
2799 free(body);
2800 if (cc != NULL)
2801 free(cc);
2802 if (from != NULL)
2803 free(from);
2804 if (on != NULL)
2805 mailimap_date_free(on);
2806 if (since != NULL)
2807 mailimap_date_free(since);
2808 if (subject != NULL)
2809 free(subject);
2810 if (text != NULL)
2811 free(text);
2812 if (to != NULL)
2813 free(to);
2814 if (header_name != NULL)
2815 free(header_name);
2816 if (header_value != NULL)
2817 free(header_value);
2818 if (not != NULL)
2819 mailimap_search_key_free(not);
2820 if (or1 != NULL)
2821 mailimap_search_key_free(or1);
2822 if (or2 != NULL)
2823 mailimap_search_key_free(or2);
2824 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2825 clist_free(multiple);
2826 err:
2827 return res;
2828}
2829#endif
2830
2831
2832int msg_list_to_imap_set(clist * msg_list,
2833 struct mailimap_set ** result)
2834{
2835 struct mailimap_set * imap_set;
2836 clistiter * cur;
2837 int previous_valid;
2838 uint32_t first_seq;
2839 uint32_t previous;
2840 int r;
2841 int res;
2842
2843 imap_set = mailimap_set_new_empty();
2844 if (imap_set == NULL) {
2845 res = MAIL_ERROR_MEMORY;
2846 goto err;
2847 }
2848
2849 cur = clist_begin(msg_list);
2850 previous_valid = FALSE;
2851 first_seq = 0;
2852 previous = 0;
2853 while (1) {
2854 uint32_t * pindex;
2855
2856 if ((cur == NULL) && (previous_valid)) {
2857 if (first_seq == previous) {
2858 r = mailimap_set_add_single(imap_set, first_seq);
2859 if (r != MAILIMAP_NO_ERROR) {
2860 res = r;
2861 goto free;
2862 }
2863 }
2864 else {
2865 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2866 if (r != MAILIMAP_NO_ERROR) {
2867 res = r;
2868 goto free;
2869 }
2870 }
2871 break;
2872 }
2873
2874 pindex = clist_content(cur);
2875
2876 if (!previous_valid) {
2877 first_seq = * pindex;
2878 previous_valid = TRUE;
2879 previous = * pindex;
2880 cur = clist_next(cur);
2881 }
2882 else {
2883 if (* pindex != previous + 1) {
2884 if (first_seq == previous) {
2885 r = mailimap_set_add_single(imap_set, first_seq);
2886 if (r != MAILIMAP_NO_ERROR) {
2887 res = r;
2888 goto free;
2889 }
2890 }
2891 else {
2892 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2893 if (r != MAILIMAP_NO_ERROR) {
2894 res = r;
2895 goto free;
2896 }
2897 }
2898 previous_valid = FALSE;
2899 }
2900 else {
2901 previous = * pindex;
2902 cur = clist_next(cur);
2903 }
2904 }
2905 }
2906
2907 * result = imap_set;
2908
2909 return MAIL_NO_ERROR;
2910
2911 free:
2912 mailimap_set_free(imap_set);
2913 err:
2914 return res;
2915}
2916
2917
2918static int
2919uid_list_to_env_list(clist * fetch_result,
2920 struct mailmessage_list ** result,
2921 mailsession * session, mailmessage_driver * driver)
2922{
2923 clistiter * cur;
2924 struct mailmessage_list * env_list;
2925 int r;
2926 int res;
2927 carray * tab;
2928 unsigned int i;
2929 mailmessage * msg;
2930
2931 tab = carray_new(128);
2932 if (tab == NULL) {
2933 res = MAIL_ERROR_MEMORY;
2934 goto err;
2935 }
2936
2937 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2938 cur = clist_next(cur)) {
2939 struct mailimap_msg_att * msg_att;
2940 clistiter * item_cur;
2941 uint32_t uid;
2942 size_t size;
2943
2944 msg_att = clist_content(cur);
2945
2946 uid = 0;
2947 size = 0;
2948 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2949 item_cur = clist_next(item_cur)) {
2950 struct mailimap_msg_att_item * item;
2951
2952 item = clist_content(item_cur);
2953
2954 switch (item->att_type) {
2955 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2956 switch (item->att_data.att_static->att_type) {
2957 case MAILIMAP_MSG_ATT_UID:
2958 uid = item->att_data.att_static->att_data.att_uid;
2959 break;
2960
2961 case MAILIMAP_MSG_ATT_RFC822_SIZE:
2962 size = item->att_data.att_static->att_data.att_rfc822_size;
2963 break;
2964 }
2965 break;
2966 }
2967 }
2968
2969 msg = mailmessage_new();
2970 if (msg == NULL) {
2971 res = MAIL_ERROR_MEMORY;
2972 goto free_list;
2973 }
2974
2975 r = mailmessage_init(msg, session, driver, uid, size);
2976 if (r != MAIL_NO_ERROR) {
2977 res = r;
2978 goto free_msg;
2979 }
2980
2981 r = carray_add(tab, msg, NULL);
2982 if (r < 0) {
2983 res = MAIL_ERROR_MEMORY;
2984 goto free_msg;
2985 }
2986 }
2987
2988 env_list = mailmessage_list_new(tab);
2989 if (env_list == NULL) {
2990 res = MAIL_ERROR_MEMORY;
2991 goto free_list;
2992 }
2993
2994 * result = env_list;
2995
2996 return MAIL_NO_ERROR;
2997
2998 free_msg:
2999 mailmessage_free(msg);
3000 free_list:
3001 for(i = 0 ; i < carray_count(tab) ; i++)
3002 mailmessage_free(carray_get(tab, i));
3003 err:
3004 return res;
3005}
3006
3007
3008/*
3009 MAILIMAP_FLAG_FETCH_RECENT,
3010 MAILIMAP_FLAG_FETCH_OTHER
3011
3012 MAILIMAP_FLAG_ANSWERED,
3013 MAILIMAP_FLAG_FLAGGED,
3014 MAILIMAP_FLAG_DELETED,
3015 MAILIMAP_FLAG_SEEN,
3016 MAILIMAP_FLAG_DRAFT,
3017 MAILIMAP_FLAG_KEYWORD,
3018 MAILIMAP_FLAG_EXTENSION
3019*/
3020
3021static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
3022 struct mail_flags ** result)
3023{
3024 struct mail_flags * flags;
3025 clist * flag_list;
3026 clistiter * cur;
3027
3028 flags = mail_flags_new_empty();
3029 if (flags == NULL)
3030 goto err;
3031 flags->fl_flags = 0;
3032
3033 flag_list = att_dyn->att_list;
3034 if (flag_list != NULL) {
3035 for(cur = clist_begin(flag_list) ; cur != NULL ;
3036 cur = clist_next(cur)) {
3037 struct mailimap_flag_fetch * flag_fetch;
3038
3039 flag_fetch = clist_content(cur);
3040 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
3041 flags->fl_flags |= MAIL_FLAG_NEW;
3042 else {
3043 char * keyword;
3044 int r;
3045
3046 switch (flag_fetch->fl_flag->fl_type) {
3047 case MAILIMAP_FLAG_ANSWERED:
3048 flags->fl_flags |= MAIL_FLAG_ANSWERED;
3049 break;
3050 case MAILIMAP_FLAG_FLAGGED:
3051 flags->fl_flags |= MAIL_FLAG_FLAGGED;
3052 break;
3053 case MAILIMAP_FLAG_DELETED:
3054 flags->fl_flags |= MAIL_FLAG_DELETED;
3055 break;
3056 case MAILIMAP_FLAG_SEEN:
3057 flags->fl_flags |= MAIL_FLAG_SEEN;
3058 break;
3059 case MAILIMAP_FLAG_DRAFT:
3060 keyword = strdup("Draft");
3061 if (keyword == NULL)
3062 goto free;
3063 r = clist_append(flags->fl_extension, keyword);
3064 if (r < 0) {
3065 free(keyword);
3066 goto free;
3067 }
3068 break;
3069 case MAILIMAP_FLAG_KEYWORD:
3070 if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword,
3071 "$Forwarded") == 0) {
3072 flags->fl_flags |= MAIL_FLAG_FORWARDED;
3073 }
3074 else {
3075 keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword);
3076 if (keyword == NULL)
3077 goto free;
3078 r = clist_append(flags->fl_extension, keyword);
3079 if (r < 0) {
3080 free(keyword);
3081 goto free;
3082 }
3083 }
3084 break;
3085 case MAILIMAP_FLAG_EXTENSION:
3086 /* do nothing */
3087 break;
3088 }
3089 }
3090 }
3091 /*
3092 MAIL_FLAG_NEW was set for \Recent messages.
3093 Correct this flag for \Seen messages by unsetting it.
3094 */
3095 if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) {
3096 flags->fl_flags &= ~MAIL_FLAG_NEW;
3097 }
3098 }
3099
3100 * result = flags;
3101
3102 return MAIL_NO_ERROR;
3103
3104 free:
3105 mail_flags_free(flags);
3106 err:
3107 return MAIL_ERROR_MEMORY;
3108}
3109
3110int imap_flags_to_imap_flags(struct mail_flags * flags,
3111 struct mailimap_flag_list ** result)
3112{
3113 struct mailimap_flag * flag;
3114 struct mailimap_flag_list * flag_list;
3115 int res;
3116 clistiter * cur;
3117 int r;
3118
3119 flag_list = mailimap_flag_list_new_empty();
3120 if (flag_list == NULL) {
3121 res = MAIL_ERROR_MEMORY;
3122 goto err;
3123 }
3124
3125 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) {
3126 flag = mailimap_flag_new_deleted();
3127 if (flag == NULL) {
3128 res = MAIL_ERROR_MEMORY;
3129 goto free_flag_list;
3130 }
3131 r = mailimap_flag_list_add(flag_list, flag);
3132 if (r != MAILIMAP_NO_ERROR) {
3133 mailimap_flag_free(flag);
3134 res = MAIL_ERROR_MEMORY;
3135 goto free_flag_list;
3136 }
3137 }
3138
3139 if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) {
3140 flag = mailimap_flag_new_flagged();
3141 if (flag == NULL) {
3142 res = MAIL_ERROR_MEMORY;
3143 goto free_flag_list;
3144 }
3145 r = mailimap_flag_list_add(flag_list, flag);
3146 if (r != MAILIMAP_NO_ERROR) {
3147 mailimap_flag_free(flag);
3148 res = MAIL_ERROR_MEMORY;
3149 goto free_flag_list;
3150 }
3151 }
3152
3153 if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) {
3154 flag = mailimap_flag_new_seen();
3155 if (flag == NULL) {
3156 res = MAIL_ERROR_MEMORY;
3157 goto free_flag_list;
3158 }
3159 r = mailimap_flag_list_add(flag_list, flag);
3160 if (r != MAILIMAP_NO_ERROR) {
3161 res = MAIL_ERROR_MEMORY;
3162 goto free_flag_list;
3163 }
3164 }
3165
3166 if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) {
3167 flag = mailimap_flag_new_answered();
3168 if (flag == NULL) {
3169 res = MAIL_ERROR_MEMORY;
3170 goto free_flag_list;
3171 }
3172 r = mailimap_flag_list_add(flag_list, flag);
3173 if (r != MAILIMAP_NO_ERROR) {
3174 mailimap_flag_free(flag);
3175 res = MAIL_ERROR_MEMORY;
3176 goto free_flag_list;
3177 }
3178 }
3179
3180 if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) {
3181 char * flag_str;
3182
3183 flag_str = strdup("$Forwarded");
3184 if (flag_str == NULL) {
3185 res = MAIL_ERROR_MEMORY;
3186 goto free_flag_list;
3187 }
3188 flag = mailimap_flag_new_flag_keyword(flag_str);
3189 if (flag == NULL) {
3190 free(flag_str);
3191 res = MAIL_ERROR_MEMORY;
3192 goto free_flag_list;
3193 }
3194 r = mailimap_flag_list_add(flag_list, flag);
3195 if (r != MAILIMAP_NO_ERROR) {
3196 mailimap_flag_free(flag);
3197 res = MAIL_ERROR_MEMORY;
3198 goto free_flag_list;
3199 }
3200 }
3201
3202 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
3203 cur = clist_next(cur)) {
3204 char * flag_str;
3205
3206 flag_str = clist_content(cur);
3207
3208 if (strcasecmp(flag_str, "Draft") == 0) {
3209 flag = mailimap_flag_new_draft();
3210 if (flag == NULL) {
3211 res = MAIL_ERROR_MEMORY;
3212 goto free_flag_list;
3213 }
3214 r = mailimap_flag_list_add(flag_list, flag);
3215 if (r != MAILIMAP_NO_ERROR) {
3216 mailimap_flag_free(flag);
3217 res = MAIL_ERROR_MEMORY;
3218 goto free_flag_list;
3219 }
3220 }
3221 else {
3222 flag_str = strdup(flag_str);
3223 if (flag_str == NULL) {
3224 res = MAIL_ERROR_MEMORY;
3225 goto free_flag_list;
3226 }
3227 flag = mailimap_flag_new_flag_keyword(flag_str);
3228 if (flag == NULL) {
3229 free(flag_str);
3230 res = MAIL_ERROR_MEMORY;
3231 goto free_flag_list;
3232 }
3233 r = mailimap_flag_list_add(flag_list, flag);
3234 if (r != MAILIMAP_NO_ERROR) {
3235 mailimap_flag_free(flag);
3236 res = MAIL_ERROR_MEMORY;
3237 goto free_flag_list;
3238 }
3239 }
3240 }
3241
3242 * result = flag_list;
3243
3244 return MAIL_NO_ERROR;
3245
3246 free_flag_list:
3247 mailimap_flag_list_free(flag_list);
3248 err:
3249 return res;
3250}
3251
3252static int flags_to_imap_flags(struct mail_flags * flags,
3253 struct mailimap_store_att_flags ** result)
3254{
3255 struct mailimap_flag_list * flag_list;
3256 struct mailimap_store_att_flags * att_flags;
3257 int res;
3258 int r;
3259
3260 r = imap_flags_to_imap_flags(flags,
3261 &flag_list);
3262 if (r != MAIL_NO_ERROR) {
3263 res = r;
3264 goto err;
3265 }
3266
3267 att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list);
3268 if (att_flags == NULL) {
3269 res = MAIL_ERROR_MEMORY;
3270 goto free_flag_list;
3271 }
3272
3273 * result = att_flags;
3274
3275 return MAIL_NO_ERROR;
3276
3277 free_flag_list:
3278 mailimap_flag_list_free(flag_list);
3279 err:
3280 return res;
3281}
3282
3283
3284static int
3285imap_fetch_result_to_flags(clist * fetch_result, uint32_t index,
3286 struct mail_flags ** result)
3287{
3288 clistiter * cur;
3289 int r;
3290
3291 for(cur = clist_begin(fetch_result) ; cur != NULL ;
3292 cur = clist_next(cur)) {
3293 struct mailimap_msg_att * msg_att;
3294 clistiter * item_cur;
3295 uint32_t uid;
3296 struct mailimap_msg_att_dynamic * att_dyn;
3297
3298 msg_att = clist_content(cur);
3299
3300 uid = 0;
3301 att_dyn = NULL;
3302
3303 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
3304 item_cur = clist_next(item_cur)) {
3305 struct mailimap_msg_att_item * item;
3306
3307 item = clist_content(item_cur);
3308
3309 if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
3310 switch (item->att_data.att_static->att_type) {
3311 case MAILIMAP_MSG_ATT_UID:
3312 uid = item->att_data.att_static->att_data.att_uid;
3313 break;
3314 }
3315 }
3316 else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) {
3317 if (att_dyn == NULL) {
3318 att_dyn = item->att_data.att_dyn;
3319 }
3320 }
3321 }
3322
3323 if (uid != 0) {
3324 if (uid == index) {
3325 struct mail_flags * flags;
3326
3327 if (att_dyn != NULL) {
3328 r = imap_flags_to_flags(att_dyn, &flags);
3329
3330 if (r == MAIL_NO_ERROR) {
3331 * result = flags;
3332 return MAIL_NO_ERROR;
3333 }
3334 }
3335 }
3336 }
3337 }
3338
3339 return MAIL_ERROR_MSG_NOT_FOUND;
3340}
3341
3342
3343int imap_fetch_flags(mailimap * imap,
3344 uint32_t index, struct mail_flags ** result)
3345{
3346 struct mailimap_fetch_att * fetch_att;
3347 struct mailimap_fetch_type * fetch_type;
3348 struct mailimap_set * set;
3349 int r;
3350 int res;
3351 clist * fetch_result;
3352 struct mail_flags * flags;
3353
3354 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3355 if (fetch_type == NULL) {
3356 res = MAIL_ERROR_MEMORY;
3357 goto err;
3358 }
3359
3360 fetch_att = mailimap_fetch_att_new_uid();
3361 if (fetch_att == NULL) {
3362 res = MAIL_ERROR_MEMORY;
3363 goto free_fetch_type;
3364 }
3365
3366 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3367 if (r != MAILIMAP_NO_ERROR) {
3368 mailimap_fetch_att_free(fetch_att);
3369 res = MAIL_ERROR_MEMORY;
3370 goto free_fetch_type;
3371 }
3372
3373 fetch_att = mailimap_fetch_att_new_flags();
3374 if (fetch_att == NULL) {
3375 res = MAIL_ERROR_MEMORY;
3376 goto free_fetch_type;
3377 }
3378
3379 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3380 if (r != MAILIMAP_NO_ERROR) {
3381 mailimap_fetch_att_free(fetch_att);
3382 res = MAIL_ERROR_MEMORY;
3383 goto free_fetch_type;
3384 }
3385
3386 set = mailimap_set_new_single(index);
3387 if (set == NULL) {
3388 res = MAIL_ERROR_MEMORY;
3389 goto free_fetch_type;
3390 }
3391
3392 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
3393
3394 mailimap_fetch_type_free(fetch_type);
3395 mailimap_set_free(set);
3396
3397 switch (r) {
3398 case MAILIMAP_NO_ERROR:
3399 break;
3400 default:
3401 return imap_error_to_mail_error(r);
3402 }
3403
3404 r = imap_fetch_result_to_flags(fetch_result, index, &flags);
3405 mailimap_fetch_list_free(fetch_result);
3406
3407 if (r != MAIL_NO_ERROR) {
3408 res = r;
3409 goto err;
3410 }
3411
3412 * result = flags;
3413
3414 return MAIL_NO_ERROR;
3415
3416 free_fetch_type:
3417 mailimap_fetch_type_free(fetch_type);
3418 err:
3419 return res;
3420}
3421
3422int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
3423 struct mail_flags * flags)
3424{
3425 struct mailimap_store_att_flags * att_flags;
3426 struct mailimap_set * set;
3427 int r;
3428 int res;
3429
3430 set = mailimap_set_new_interval(first, last);
3431 if (set == NULL) {
3432 res = MAIL_ERROR_MEMORY;
3433 goto err;
3434 }
3435
3436 r = flags_to_imap_flags(flags, &att_flags);
3437 if (r != MAIL_NO_ERROR) {
3438 res = r;
3439 goto free_set;
3440 }
3441
3442 r = mailimap_uid_store(imap, set, att_flags);
3443 if (r != MAILIMAP_NO_ERROR) {
3444 res = imap_error_to_mail_error(r);
3445 goto free_flag;
3446 }
3447
3448 mailimap_store_att_flags_free(att_flags);
3449 mailimap_set_free(set);
3450
3451 return MAIL_NO_ERROR;
3452
3453 free_flag:
3454 mailimap_store_att_flags_free(att_flags);
3455 free_set:
3456 mailimap_set_free(set);
3457 err:
3458 return res;
3459}
3460
3461
3462
3463
3464int imap_get_messages_list(mailimap * imap,
3465 mailsession * session, mailmessage_driver * driver,
3466 uint32_t first_index,
3467 struct mailmessage_list ** result)
3468{
3469 struct mailmessage_list * env_list;
3470 int r;
3471 struct mailimap_fetch_att * fetch_att;
3472 struct mailimap_fetch_type * fetch_type;
3473 struct mailimap_set * set;
3474 clist * fetch_result;
3475 int res;
3476
3477 set = mailimap_set_new_interval(first_index, 0);
3478 if (set == NULL) {
3479 res = MAIL_ERROR_MEMORY;
3480 goto err;
3481 }
3482
3483 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3484 if (fetch_type == NULL) {
3485 res = MAIL_ERROR_MEMORY;
3486 goto free_set;
3487 }
3488
3489 fetch_att = mailimap_fetch_att_new_uid();
3490 if (fetch_att == NULL) {
3491 res = MAIL_ERROR_MEMORY;
3492 goto free_fetch_type;
3493 }
3494
3495 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3496 if (r != MAILIMAP_NO_ERROR) {
3497 mailimap_fetch_att_free(fetch_att);
3498 res = MAIL_ERROR_MEMORY;
3499 goto free_fetch_type;
3500 }
3501
3502 fetch_att = mailimap_fetch_att_new_rfc822_size();
3503 if (fetch_att == NULL) {
3504 res = MAIL_ERROR_MEMORY;
3505 goto free_fetch_type;
3506 }
3507
3508 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3509 if (r != MAILIMAP_NO_ERROR) {
3510 mailimap_fetch_att_free(fetch_att);
3511 res = MAIL_ERROR_MEMORY;
3512 goto free_fetch_type;
3513 }
3514
3515 r = mailimap_uid_fetch(imap, set,
3516 fetch_type, &fetch_result);
3517
3518 mailimap_fetch_type_free(fetch_type);
3519 mailimap_set_free(set);
3520
3521 if (r != MAILIMAP_NO_ERROR) {
3522 res = imap_error_to_mail_error(r);
3523 goto err;
3524 }
3525
3526 r = uid_list_to_env_list(fetch_result, &env_list, session, driver);
3527 mailimap_fetch_list_free(fetch_result);
3528
3529 * result = env_list;
3530
3531 return MAIL_NO_ERROR;
3532
3533 free_fetch_type:
3534 mailimap_fetch_type_free(fetch_type);
3535 free_set:
3536 mailimap_set_free(set);
3537 err:
3538 return res;
3539}
3540
3541static void generate_key_from_message(char * key, size_t size,
3542 mailmessage * msg_info,
3543 int type)
3544{
3545 switch (type) {
3546 case MAILIMAP_MSG_ATT_RFC822:
3547 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
3548 break;
3549 case MAILIMAP_MSG_ATT_RFC822_HEADER:
3550 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
3551 break;
3552 case MAILIMAP_MSG_ATT_RFC822_TEXT:
3553 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
3554 break;
3555 case MAILIMAP_MSG_ATT_ENVELOPE:
3556 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
3557 break;
3558 }
3559}
3560
3561int
3562imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
3563 MMAPString * mmapstr,
3564 mailsession * session, mailmessage * msg,
3565 struct mailimf_fields ** result)
3566{
3567#if 0
3568 mailsession * imap_session;
3569#endif
3570 mailimap * imap;
3571 int r;
3572 struct mailimf_fields * fields;
3573 int res;
3574 char keyname[PATH_MAX];
3575
3576#if 0
3577 imap_session = cached_session_get_ancestor(session);
3578 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
3579#endif
3580 imap = cached_session_get_imap_session(session);
3581
3582 generate_key_from_message(keyname, PATH_MAX,
3583 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3584
3585 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
3586 if (r != MAIL_NO_ERROR) {
3587 res = r;
3588 goto err;
3589 }
3590
3591 * result = fields;
3592
3593 return MAIL_NO_ERROR;
3594
3595err:
3596 return res;
3597}
3598
3599int
3600imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
3601 MMAPString * mmapstr,
3602 mailsession * session, mailmessage * msg,
3603 struct mailimf_fields * fields)
3604{
3605 char keyname[PATH_MAX];
3606 int r;
3607 int res;
3608
3609 generate_key_from_message(keyname, PATH_MAX,
3610 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3611
3612 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
3613 if (r != MAIL_NO_ERROR) {
3614 res = r;
3615 goto err;
3616 }
3617
3618 return MAIL_NO_ERROR;
3619
3620err:
3621 return res;
3622}
3623
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.h b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
new file mode 100644
index 0000000..e15fdda
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
@@ -0,0 +1,116 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TOOLS_H
37
38#define IMAPDRIVER_TOOLS_H
39
40#include "mailimap.h"
41#include "mailmime.h"
42#include "imapdriver_types.h"
43#include "mail_cache_db.h"
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49int imap_list_to_list(clist * imap_list, struct mail_list ** result);
50
51int
52section_to_imap_section(struct mailmime_section * section, int type,
53 struct mailimap_section ** result);
54
55int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
56 uint32_t * puid,
57 struct mailimap_envelope ** pimap_envelope,
58 char ** preferences,
59 size_t * pref_size,
60 struct mailimap_msg_att_dynamic ** patt_dyn,
61 struct mailimap_body ** pimap_body);
62
63int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type);
64
65int imap_env_to_fields(struct mailimap_envelope * env,
66 char * ref_str, size_t ref_size,
67 struct mailimf_fields ** result);
68
69int
70imap_fetch_result_to_envelop_list(clist * fetch_result,
71 struct mailmessage_list * env_list);
72
73int imap_body_to_body(struct mailimap_body * imap_body,
74 struct mailmime ** result);
75
76#if 0
77int mail_search_to_imap_search(struct mail_search_key * key,
78 struct mailimap_search_key ** result);
79#endif
80
81int msg_list_to_imap_set(clist * msg_list,
82 struct mailimap_set ** result);
83
84int imap_error_to_mail_error(int error);
85
86int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
87 struct mail_flags * flags);
88
89int imap_fetch_flags(mailimap * imap,
90 uint32_t index, struct mail_flags ** result);
91
92int imap_get_messages_list(mailimap * imap,
93 mailsession * session, mailmessage_driver * driver,
94 uint32_t first_index,
95 struct mailmessage_list ** result);
96
97int
98imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
99 MMAPString * mmapstr,
100 mailsession * session, mailmessage * msg,
101 struct mailimf_fields ** result);
102
103int
104imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
105 MMAPString * mmapstr,
106 mailsession * session, mailmessage * msg,
107 struct mailimf_fields * fields);
108
109int imap_flags_to_imap_flags(struct mail_flags * flags,
110 struct mailimap_flag_list ** result);
111
112#ifdef __cplusplus
113}
114#endif
115
116#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_types.h b/libetpan/src/driver/implementation/imap/imapdriver_types.h
new file mode 100644
index 0000000..00559dc
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_types.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TYPES_H
37
38#define IMAPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mailimap.h>
43#include <libetpan/maildriver_types.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/* IMAP driver for session */
52
53struct imap_session_state_data {
54 mailimap * imap_session;
55 char * imap_mailbox;
56 struct mail_flags_store * imap_flags_store;
57};
58
59enum {
60 IMAP_SECTION_MESSAGE,
61 IMAP_SECTION_HEADER,
62 IMAP_SECTION_MIME,
63 IMAP_SECTION_BODY
64};
65
66/* cached IMAP driver for session */
67
68enum {
69 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
70};
71
72struct imap_cached_session_state_data {
73 mailsession * imap_ancestor;
74 char * imap_quoted_mb;
75 char imap_cache_directory[PATH_MAX];
76 carray * imap_uid_list;
77};
78
79
80/* IMAP storage */
81
82/*
83 imap_mailstorage is the state data specific to the IMAP4rev1 storage.
84
85 - servername this is the name of the IMAP4rev1 server
86
87 - port is the port to connect to, on the server.
88 you give 0 to use the default port.
89
90 - command, if non-NULL the command used to connect to the
91 server instead of allowing normal TCP connections to be used.
92
93 - connection_type is the type of socket layer to use.
94 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
95 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or
96 CONNECTION_TYPE_COMMAND.
97
98 - auth_type is the authenticate mechanism to use.
99 The value can be IMAP_AUTH_TYPE_PLAIN.
100 Other values are not yet implemented.
101
102 - login is the login of the IMAP4rev1 account.
103
104 - password is the password of the IMAP4rev1 account.
105
106 - cached if this value is != 0, a persistant cache will be
107 stored on local system.
108
109 - cache_directory is the location of the cache
110*/
111
112struct imap_mailstorage {
113 char * imap_servername;
114 uint16_t imap_port;
115 char * imap_command;
116 int imap_connection_type;
117
118 int imap_auth_type;
119 char * imap_login;
120 char * imap_password;
121
122 int imap_cached;
123 char * imap_cache_directory;
124};
125
126/* this is the type of IMAP4rev1 authentication */
127
128enum {
129 IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */
130 IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
131 IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
132 IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
133 IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
134 IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
135 IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
136 IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
137};
138
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.c b/libetpan/src/driver/implementation/imap/imapstorage.c
new file mode 100644
index 0000000..0bf6ec2
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.c
@@ -0,0 +1,297 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "mail.h"
42#include "imapdriver.h"
43#include "imapdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "maildriver.h"
46
47/* imap storage */
48
49#define IMAP_DEFAULT_PORT 143
50#define IMAPS_DEFAULT_PORT 993
51
52static int imap_mailstorage_connect(struct mailstorage * storage);
53static int
54imap_mailstorage_get_folder_session(struct mailstorage * storage,
55 char * pathname, mailsession ** result);
56static void imap_mailstorage_uninitialize(struct mailstorage * storage);
57
58static mailstorage_driver imap_mailstorage_driver = {
59 .sto_name = "imap",
60 .sto_connect = imap_mailstorage_connect,
61 .sto_get_folder_session = imap_mailstorage_get_folder_session,
62 .sto_uninitialize = imap_mailstorage_uninitialize,
63};
64
65int imap_mailstorage_init(struct mailstorage * storage,
66 char * imap_servername, uint16_t imap_port,
67 char * imap_command,
68 int imap_connection_type, int imap_auth_type,
69 char * imap_login, char * imap_password,
70 int imap_cached, char * imap_cache_directory)
71{
72 struct imap_mailstorage * imap_storage;
73
74 imap_storage = malloc(sizeof(* imap_storage));
75 if (imap_storage == NULL)
76 goto err;
77
78 imap_storage->imap_servername = strdup(imap_servername);
79 if (imap_storage->imap_servername == NULL)
80 goto free;
81
82 imap_storage->imap_connection_type = imap_connection_type;
83
84 if (imap_port == 0) {
85 switch (imap_connection_type) {
86 case CONNECTION_TYPE_PLAIN:
87 case CONNECTION_TYPE_TRY_STARTTLS:
88 case CONNECTION_TYPE_STARTTLS:
89 case CONNECTION_TYPE_COMMAND:
90 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
91 case CONNECTION_TYPE_COMMAND_STARTTLS:
92 imap_port = IMAP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 imap_port = IMAPS_DEFAULT_PORT;
98 break;
99 }
100 }
101
102 imap_storage->imap_port = imap_port;
103
104 if (imap_command != NULL) {
105 imap_storage->imap_command = strdup(imap_command);
106 if (imap_storage->imap_command == NULL)
107 goto free_servername;
108 }
109 else
110 imap_storage->imap_command = NULL;
111
112 imap_storage->imap_auth_type = imap_auth_type;
113
114 if (imap_login != NULL) {
115 imap_storage->imap_login = strdup(imap_login);
116 if (imap_storage->imap_login == NULL)
117 goto free_command;
118 }
119 else
120 imap_storage->imap_login = NULL;
121
122 if (imap_password != NULL) {
123 imap_storage->imap_password = strdup(imap_password);
124 if (imap_storage->imap_password == NULL)
125 goto free_login;
126 }
127 else
128 imap_storage->imap_password = NULL;
129
130 imap_storage->imap_cached = imap_cached;
131
132 if (imap_cached && (imap_cache_directory != NULL)) {
133 imap_storage->imap_cache_directory = strdup(imap_cache_directory);
134 if (imap_storage->imap_cache_directory == NULL)
135 goto free_password;
136 }
137 else {
138 imap_storage->imap_cached = FALSE;
139 imap_storage->imap_cache_directory = NULL;
140 }
141
142 storage->sto_data = imap_storage;
143 storage->sto_driver = &imap_mailstorage_driver;
144
145 return MAIL_NO_ERROR;
146
147 free_password:
148 free(imap_storage->imap_password);
149 free_login:
150 free(imap_storage->imap_login);
151 free_command:
152 free(imap_storage->imap_command);
153 free_servername:
154 free(imap_storage->imap_servername);
155 free:
156 free(imap_storage);
157 err:
158 return MAIL_ERROR_MEMORY;
159}
160
161static void imap_mailstorage_uninitialize(struct mailstorage * storage)
162{
163 struct imap_mailstorage * imap_storage;
164
165 imap_storage = storage->sto_data;
166
167 if (imap_storage->imap_cache_directory != NULL)
168 free(imap_storage->imap_cache_directory);
169 if (imap_storage->imap_password != NULL)
170 free(imap_storage->imap_password);
171 if (imap_storage->imap_login != NULL)
172 free(imap_storage->imap_login);
173 if (imap_storage->imap_command != NULL)
174 free(imap_storage->imap_command);
175 free(imap_storage->imap_servername);
176 free(imap_storage);
177
178 storage->sto_data = NULL;
179}
180
181static int imap_connect(struct mailstorage * storage,
182 mailsession ** result)
183{
184 struct imap_mailstorage * imap_storage;
185 mailsession_driver * driver;
186 int r;
187 int res;
188 mailsession * session;
189
190 imap_storage = storage->sto_data;
191
192 if (imap_storage->imap_cached)
193 driver = imap_cached_session_driver;
194 else
195 driver = imap_session_driver;
196
197 r = mailstorage_generic_connect(driver,
198 imap_storage->imap_servername,
199 imap_storage->imap_port,
200 imap_storage->imap_command,
201 imap_storage->imap_connection_type,
202 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY,
203 imap_storage->imap_cache_directory,
204 0, NULL,
205 &session);
206 switch (r) {
207 case MAIL_NO_ERROR_NON_AUTHENTICATED:
208 case MAIL_NO_ERROR_AUTHENTICATED:
209 case MAIL_NO_ERROR:
210 break;
211 default:
212 res = r;
213 goto err;
214 }
215
216 r = mailstorage_generic_auth(session, r,
217 imap_storage->imap_connection_type,
218 imap_storage->imap_login,
219 imap_storage->imap_password);
220 if (r != MAIL_NO_ERROR) {
221 res = r;
222 goto free;
223 }
224
225 * result = session;
226
227 return MAIL_NO_ERROR;
228
229 free:
230 mailsession_free(session);
231 err:
232 return res;
233}
234
235static int imap_mailstorage_connect(struct mailstorage * storage)
236{
237 mailsession * session;
238 int r;
239 int res;
240
241 r = imap_connect(storage, &session);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto err;
245 }
246
247 r = mailsession_select_folder(session, "INBOX");
248 if (r != MAIL_NO_ERROR) {
249 mailsession_logout(session);
250 res = r;
251 goto err;
252 }
253
254 storage->sto_session = session;
255 storage->sto_driver = &imap_mailstorage_driver;
256
257 return MAIL_NO_ERROR;
258
259 err:
260 return res;
261}
262
263static int
264imap_mailstorage_get_folder_session(struct mailstorage * storage,
265 char * pathname, mailsession ** result)
266{
267 mailsession * session;
268 int r;
269 int res;
270
271 if (strcasecmp(pathname, "INBOX") == 0) {
272 session = storage->sto_session;
273 }
274 else {
275 r = imap_connect(storage, &session);
276 if (r != MAIL_NO_ERROR) {
277 res = r;
278 goto err;
279 }
280
281 r = mailsession_select_folder(session, pathname);
282 if (r != MAIL_NO_ERROR) {
283 mailsession_logout(session);
284 res = r;
285 goto free;
286 }
287 }
288
289 * result = session;
290
291 return MAIL_NO_ERROR;
292
293 free:
294 mailsession_free(session);
295 err:
296 return res;
297}
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.h b/libetpan/src/driver/implementation/imap/imapstorage.h
new file mode 100644
index 0000000..929a86e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.h
@@ -0,0 +1,90 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPSTORAGE_H
37
38#define IMAPSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46/*
47 imap_mailstorage_init is the constructor for a IMAP4rev1 storage
48
49 @param storage this is the storage to initialize.
50
51 @param servername this is the name of the IMAP4rev1 server
52
53 @param port is the port to connect to, on the server.
54 you give 0 to use the default port.
55
56 @param command the command used to connect to the server instead of
57 allowing normal TCP connections to be used.
58
59 @param connection_type is the type of socket layer to use.
60 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
61 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
62 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
63 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
64
65 @param auth_type is the authenticate mechanism to use.
66 The value can be IMAP_AUTH_TYPE_PLAIN.
67 Other values are not yet implemented.
68
69 @param login is the login of the IMAP4rev1 account.
70
71 @param password is the password of the IMAP4rev1 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77*/
78
79int imap_mailstorage_init(struct mailstorage * storage,
80 char * imap_servername, uint16_t imap_port,
81 char * imap_command,
82 int imap_connection_type, int imap_auth_type,
83 char * imap_login, char * imap_password,
84 int imap_cached, char * imap_cache_directory);
85
86#ifdef __cplusplus
87}
88#endif
89
90#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver.c b/libetpan/src/driver/implementation/maildir/maildirdriver.c
new file mode 100644
index 0000000..a97fd43
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver.c
@@ -0,0 +1,676 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36
37/*
38 flags directory MUST be kept so that we can have other flags
39 than standards
40*/
41
42#include "maildirdriver.h"
43
44#include <stdio.h>
45#include <sys/types.h>
46#include <dirent.h>
47#include <unistd.h>
48#include <sys/stat.h>
49#include <ctype.h>
50#include <fcntl.h>
51#include <sys/mman.h>
52#include <stdlib.h>
53#include <string.h>
54
55#include "maildir.h"
56#include "maildriver_tools.h"
57#include "maildirdriver_message.h"
58#include "maildirdriver_tools.h"
59#include "mailmessage.h"
60#include "generic_cache.h"
61
62static int initialize(mailsession * session);
63
64static void uninitialize(mailsession * session);
65
66static int connect_path(mailsession * session, char * path);
67
68static int logout(mailsession * session);
69
70static int expunge_folder(mailsession * session);
71
72static int status_folder(mailsession * session, char * mb,
73 uint32_t * result_messages, uint32_t * result_recent,
74 uint32_t * result_unseen);
75
76static int recent_number(mailsession * session, char * mb,
77 uint32_t * result);
78
79static int unseen_number(mailsession * session, char * mb,
80 uint32_t * result);
81
82static int messages_number(mailsession * session, char * mb,
83 uint32_t * result);
84
85static int append_message(mailsession * session,
86 char * message, size_t size);
87
88static int append_message_flags(mailsession * session,
89 char * message, size_t size, struct mail_flags * flags);
90
91static int get_messages_list(mailsession * session,
92 struct mailmessage_list ** result);
93
94static int get_envelopes_list(mailsession * session,
95 struct mailmessage_list * env_list);
96
97static int check_folder(mailsession * session);
98
99static int get_message_by_uid(mailsession * session,
100 const char * uid, mailmessage ** result);
101
102static mailsession_driver local_maildir_session_driver = {
103 .sess_name = "maildir",
104
105 .sess_initialize = initialize,
106 .sess_uninitialize = uninitialize,
107
108 .sess_parameters = NULL,
109
110 .sess_connect_stream = NULL,
111 .sess_connect_path = connect_path,
112 .sess_starttls = NULL,
113 .sess_login = NULL,
114 .sess_logout = logout,
115 .sess_noop = NULL,
116
117 .sess_build_folder_name = NULL,
118 .sess_create_folder = NULL,
119 .sess_delete_folder = NULL,
120 .sess_rename_folder = NULL,
121 .sess_check_folder = check_folder,
122 .sess_examine_folder = NULL,
123 .sess_select_folder = NULL,
124 .sess_expunge_folder = expunge_folder,
125 .sess_status_folder = status_folder,
126 .sess_messages_number = messages_number,
127 .sess_recent_number = recent_number,
128 .sess_unseen_number = unseen_number,
129 .sess_list_folders = NULL,
130 .sess_lsub_folders = NULL,
131 .sess_subscribe_folder = NULL,
132 .sess_unsubscribe_folder = NULL,
133
134 .sess_append_message = append_message,
135 .sess_append_message_flags = append_message_flags,
136 .sess_copy_message = NULL,
137 .sess_move_message = NULL,
138
139 .sess_get_messages_list = get_messages_list,
140 .sess_get_envelopes_list = get_envelopes_list,
141 .sess_remove_message = NULL,
142#if 0
143 .sess_search_messages = maildriver_generic_search_messages,
144#endif
145
146 .sess_get_message = NULL,
147 .sess_get_message_by_uid = get_message_by_uid,
148};
149
150mailsession_driver * maildir_session_driver = &local_maildir_session_driver;
151
152
153static int flags_store_process(struct maildir * md,
154 struct mail_flags_store * flags_store);
155
156
157static inline struct maildir_session_state_data * get_data(mailsession * session)
158{
159 return session->sess_data;
160}
161
162static struct maildir * get_maildir_session(mailsession * session)
163{
164 return get_data(session)->md_session;
165}
166
167static int initialize(mailsession * session)
168{
169 struct maildir_session_state_data * data;
170
171 data = malloc(sizeof(* data));
172 if (data == NULL)
173 goto err;
174
175 data->md_session = NULL;
176
177 data->md_flags_store = mail_flags_store_new();
178 if (data->md_flags_store == NULL)
179 goto free;
180
181 session->sess_data = data;
182
183 return MAIL_NO_ERROR;
184
185 free:
186 free(data);
187 err:
188 return MAIL_ERROR_MEMORY;
189}
190
191static void uninitialize(mailsession * session)
192{
193 struct maildir_session_state_data * data;
194
195 data = get_data(session);
196
197 if (data->md_session != NULL)
198 flags_store_process(data->md_session, data->md_flags_store);
199
200 mail_flags_store_free(data->md_flags_store);
201 if (data->md_session != NULL)
202 maildir_free(data->md_session);
203
204 free(data);
205
206 session->sess_data = NULL;
207}
208
209
210static int connect_path(mailsession * session, char * path)
211{
212 struct maildir * md;
213 int res;
214 int r;
215
216 if (get_maildir_session(session) != NULL) {
217 res = MAIL_ERROR_BAD_STATE;
218 goto err;
219 }
220
221 md = maildir_new(path);
222 if (md == NULL) {
223 res = MAIL_ERROR_MEMORY;
224 goto err;
225 }
226
227 r = maildir_update(md);
228 if (r != MAILDIR_NO_ERROR) {
229 res = maildirdriver_maildir_error_to_mail_error(r);
230 goto free;
231 }
232
233 get_data(session)->md_session = md;
234
235 return MAIL_NO_ERROR;
236
237 free:
238 maildir_free(md);
239 err:
240 return res;
241}
242
243static int logout(mailsession * session)
244{
245 struct maildir * md;
246
247 check_folder(session);
248
249 md = get_maildir_session(session);
250 if (md == NULL)
251 return MAIL_ERROR_BAD_STATE;
252
253 maildir_free(md);
254 get_data(session)->md_session = NULL;
255
256 return MAIL_NO_ERROR;
257}
258
259/* folders operations */
260
261static int status_folder(mailsession * session, char * mb,
262 uint32_t * result_messages, uint32_t * result_recent,
263 uint32_t * result_unseen)
264{
265 int r;
266 struct maildir * md;
267 unsigned int i;
268 uint32_t messages;
269 uint32_t recent;
270 uint32_t unseen;
271
272 check_folder(session);
273
274 md = get_maildir_session(session);
275 if (md == NULL)
276 return MAIL_ERROR_BAD_STATE;
277
278 r = maildir_update(md);
279 if (r != MAILDIR_NO_ERROR)
280 return maildirdriver_maildir_error_to_mail_error(r);
281
282 messages = 0;
283 recent = 0;
284 unseen = 0;
285 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) {
286 struct maildir_msg * msg;
287
288 msg = carray_get(md->mdir_msg_list, i);
289 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
290 recent ++;
291 if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0)
292 unseen ++;
293 messages ++;
294 }
295
296 * result_messages = messages;
297 * result_recent = recent;
298 * result_unseen = unseen;
299
300 return MAIL_NO_ERROR;
301}
302
303static int messages_number(mailsession * session, char * mb,
304 uint32_t * result)
305{
306 struct maildir * md;
307 int r;
308
309 md = get_maildir_session(session);
310 if (md == NULL)
311 return MAIL_ERROR_BAD_STATE;
312
313 r = maildir_update(md);
314 if (r != MAILDIR_NO_ERROR)
315 return maildirdriver_maildir_error_to_mail_error(r);
316
317 * result = carray_count(md->mdir_msg_list);
318
319 return MAIL_NO_ERROR;
320}
321
322static int unseen_number(mailsession * session, char * mb,
323 uint32_t * result)
324{
325 uint32_t messages;
326 uint32_t recent;
327 uint32_t unseen;
328 int r;
329
330 r = status_folder(session, mb, &messages, &recent, &unseen);
331 if (r != MAIL_NO_ERROR)
332 return r;
333
334 * result = unseen;
335
336 return MAIL_NO_ERROR;
337}
338
339static int recent_number(mailsession * session, char * mb,
340 uint32_t * result)
341{
342 uint32_t messages;
343 uint32_t recent;
344 uint32_t unseen;
345 int r;
346
347 r = status_folder(session, mb, &messages, &recent, &unseen);
348 if (r != MAIL_NO_ERROR)
349 return r;
350
351 * result = recent;
352
353 return MAIL_NO_ERROR;
354}
355
356
357/* messages operations */
358
359static int append_message(mailsession * session,
360 char * message, size_t size)
361{
362#if 0
363 struct maildir * md;
364 int r;
365
366 md = get_maildir_session(session);
367 if (md == NULL)
368 return MAIL_ERROR_BAD_STATE;
369
370 r = maildir_message_add(md, message, size);
371 if (r != MAILDIR_NO_ERROR)
372 return maildirdriver_maildir_error_to_mail_error(r);
373
374 return MAIL_NO_ERROR;
375#endif
376
377 return append_message_flags(session, message, size, NULL);
378}
379
380static int append_message_flags(mailsession * session,
381 char * message, size_t size, struct mail_flags * flags)
382{
383 struct maildir * md;
384 int r;
385 char uid[PATH_MAX];
386 struct maildir_msg * md_msg;
387 chashdatum key;
388 chashdatum value;
389 uint32_t md_flags;
390
391 md = get_maildir_session(session);
392 if (md == NULL)
393 return MAIL_ERROR_BAD_STATE;
394
395 r = maildir_message_add_uid(md, message, size,
396 uid, sizeof(uid));
397 if (r != MAILDIR_NO_ERROR)
398 return maildirdriver_maildir_error_to_mail_error(r);
399
400 if (flags == NULL)
401 goto exit;
402
403 key.data = uid;
404 key.len = strlen(uid);
405 r = chash_get(md->mdir_msg_hash, &key, &value);
406 if (r < 0)
407 goto exit;
408
409 md_msg = value.data;
410
411 md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
412
413 r = maildir_message_change_flags(md, uid, md_flags);
414 if (r != MAILDIR_NO_ERROR)
415 goto exit;
416
417 return MAIL_NO_ERROR;
418
419 exit:
420 return MAIL_NO_ERROR;
421}
422
423static int get_messages_list(mailsession * session,
424 struct mailmessage_list ** result)
425{
426 struct maildir * md;
427 int r;
428 struct mailmessage_list * env_list;
429 int res;
430
431 md = get_maildir_session(session);
432 if (md == NULL)
433 return MAIL_ERROR_BAD_STATE;
434
435 r = maildir_update(md);
436 if (r != MAILDIR_NO_ERROR) {
437 res = maildirdriver_maildir_error_to_mail_error(r);
438 goto err;
439 }
440
441 r = maildir_get_messages_list(session, md,
442 maildir_message_driver, &env_list);
443 if (r != MAILDIR_NO_ERROR) {
444 res = r;
445 goto free_list;
446 }
447
448 * result = env_list;
449
450 return MAIL_NO_ERROR;
451
452 free_list:
453 mailmessage_list_free(env_list);
454 err:
455 return res;
456}
457
458static int get_envelopes_list(mailsession * session,
459 struct mailmessage_list * env_list)
460{
461 int r;
462 struct maildir * md;
463 unsigned int i;
464 int res;
465
466 check_folder(session);
467
468 md = get_maildir_session(session);
469 if (md == NULL) {
470 res = MAIL_ERROR_BAD_STATE;
471 goto err;
472 }
473
474 r = maildir_update(md);
475 if (r != MAILDIR_NO_ERROR) {
476 res = maildirdriver_maildir_error_to_mail_error(r);
477 goto err;
478 }
479
480 r = maildriver_generic_get_envelopes_list(session, env_list);
481 if (r != MAIL_NO_ERROR) {
482 res = r;
483 goto err;
484 }
485
486 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
487 struct maildir_msg * md_msg;
488 mailmessage * msg;
489 uint32_t driver_flags;
490 clist * ext;
491 chashdatum key;
492 chashdatum value;
493
494 msg = carray_get(env_list->msg_tab, i);
495
496 key.data = msg->msg_uid;
497 key.len = strlen(msg->msg_uid);
498 r = chash_get(md->mdir_msg_hash, &key, &value);
499 if (r < 0)
500 continue;
501
502 md_msg = value.data;
503
504 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
505
506 if (msg->msg_flags == NULL) {
507 ext = clist_new();
508 if (ext == NULL) {
509 res = MAIL_ERROR_MEMORY;
510 continue;
511 }
512
513 msg->msg_flags = mail_flags_new(driver_flags, ext);
514 if (msg->msg_flags == NULL) {
515 clist_free(ext);
516 res = MAIL_ERROR_MEMORY;
517 continue;
518 }
519
520 if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) {
521 mail_flags_store_set(get_data(session)->md_flags_store, msg);
522 }
523 }
524 else {
525 msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED;
526 msg->msg_flags->fl_flags |= driver_flags;
527 }
528 }
529
530 return MAIL_NO_ERROR;
531
532 err:
533 return res;
534}
535
536
537static int expunge_folder(mailsession * session)
538{
539 unsigned int i;
540 int r;
541 int res;
542 struct maildir * md;
543
544 check_folder(session);
545
546 md = get_maildir_session(session);
547 if (md == NULL)
548 return MAIL_ERROR_BAD_STATE;
549
550 r = maildir_update(md);
551 if (r != MAILDIR_NO_ERROR) {
552 res = maildirdriver_maildir_error_to_mail_error(r);
553 goto err;
554 }
555
556 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
557 struct maildir_msg * md_msg;
558
559 md_msg = carray_get(md->mdir_msg_list, i);
560
561 if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0)
562 maildir_message_remove(md, md_msg->msg_uid);
563 }
564
565 return MAIL_NO_ERROR;
566
567 err:
568 return res;
569}
570
571
572static int flags_store_process(struct maildir * md,
573 struct mail_flags_store * flags_store)
574{
575 unsigned int i;
576
577 if (carray_count(flags_store->fls_tab) == 0)
578 return MAIL_NO_ERROR;
579
580 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
581 mailmessage * msg;
582 uint32_t md_flags;
583
584 msg = carray_get(flags_store->fls_tab, i);
585 md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags);
586 md_flags &= ~MAILDIR_FLAG_NEW;
587
588 maildir_message_change_flags(md, msg->msg_uid, md_flags);
589 }
590
591 mail_flags_store_clear(flags_store);
592
593 return MAIL_NO_ERROR;
594}
595
596
597
598static int check_folder(mailsession * session)
599{
600 struct mail_flags_store * flags_store;
601 struct maildir_session_state_data * data;
602 struct maildir * md;
603
604 md = get_maildir_session(session);
605 if (md == NULL)
606 return MAIL_ERROR_BAD_STATE;
607
608 data = get_data(session);
609 flags_store = data->md_flags_store;
610
611 return flags_store_process(md, flags_store);
612}
613
614static int get_message_by_uid(mailsession * session,
615 const char * uid, mailmessage ** result)
616{
617 int r;
618 struct maildir * md;
619 int res;
620 mailmessage * msg;
621 char * msg_filename;
622 struct stat stat_info;
623
624 md = get_maildir_session(session);
625
626 /* update maildir data */
627
628 r = maildir_update(md);
629 if (r != MAILDIR_NO_ERROR) {
630 res = maildirdriver_maildir_error_to_mail_error(r);
631 goto err;
632 }
633
634 msg_filename = maildir_message_get(md, uid);
635 if (msg_filename == NULL) {
636 res = MAIL_ERROR_INVAL;
637 goto err;
638 }
639
640 r = stat(msg_filename, &stat_info);
641 free(msg_filename);
642 if (r < 0) {
643 res = MAIL_ERROR_INVAL;
644 goto err;
645 }
646
647 /* create message */
648
649 msg = mailmessage_new();
650 if (msg == NULL) {
651 res = MAIL_ERROR_MEMORY;
652 goto err;
653 }
654
655 r = mailmessage_init(msg, session, maildir_message_driver,
656 0, stat_info.st_size);
657 if (r != MAIL_NO_ERROR) {
658 mailmessage_free(msg);
659 res = r;
660 goto err;
661 }
662
663 msg->msg_uid = strdup(uid);
664 if (msg->msg_uid == NULL) {
665 mailmessage_free(msg);
666 res = r;
667 goto err;
668 }
669
670 * result = msg;
671
672 return MAIL_NO_ERROR;
673
674 err:
675 return res;
676}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver.h b/libetpan/src/driver/implementation/maildir/maildirdriver.h
new file mode 100644
index 0000000..0abe09d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_H
37
38#define MAILDIRDRIVER_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c
new file mode 100644
index 0000000..3664362
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c
@@ -0,0 +1,1158 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mail.h"
50#include "maildir.h"
51#include "maildriver_tools.h"
52#include "maildirdriver_tools.h"
53#include "maildirdriver_cached_message.h"
54#include "mailmessage.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "mail_cache_db.h"
58#include "libetpan-config.h"
59
60static int initialize(mailsession * session);
61
62static void uninitialize(mailsession * session);
63
64static int parameters(mailsession * session,
65 int id, void * value);
66
67static int connect_path(mailsession * session, char * path);
68
69static int logout(mailsession * session);
70
71static int expunge_folder(mailsession * session);
72
73static int status_folder(mailsession * session, char * mb,
74 uint32_t * result_messages, uint32_t * result_recent,
75 uint32_t * result_unseen);
76
77static int recent_number(mailsession * session, char * mb,
78 uint32_t * result);
79
80static int unseen_number(mailsession * session, char * mb,
81 uint32_t * result);
82
83static int messages_number(mailsession * session, char * mb,
84 uint32_t * result);
85
86static int append_message(mailsession * session,
87 char * message, size_t size);
88
89static int append_message_flags(mailsession * session,
90 char * message, size_t size, struct mail_flags * flags);
91
92static int get_messages_list(mailsession * session,
93 struct mailmessage_list ** result);
94
95static int get_envelopes_list(mailsession * session,
96 struct mailmessage_list * env_list);
97
98static int check_folder(mailsession * session);
99
100static int get_message(mailsession * session,
101 uint32_t num, mailmessage ** result);
102
103static int get_message_by_uid(mailsession * session,
104 const char * uid, mailmessage ** result);
105
106static mailsession_driver local_maildir_cached_session_driver = {
107 .sess_name = "maildir-cached",
108
109 .sess_initialize = initialize,
110 .sess_uninitialize = uninitialize,
111
112 .sess_parameters = parameters,
113
114 .sess_connect_stream = NULL,
115 .sess_connect_path = connect_path,
116 .sess_starttls = NULL,
117 .sess_login = NULL,
118 .sess_logout = logout,
119 .sess_noop = NULL,
120
121 .sess_build_folder_name = NULL,
122 .sess_create_folder = NULL,
123 .sess_delete_folder = NULL,
124 .sess_rename_folder = NULL,
125 .sess_check_folder = check_folder,
126 .sess_examine_folder = NULL,
127 .sess_select_folder = NULL,
128 .sess_expunge_folder = expunge_folder,
129 .sess_status_folder = status_folder,
130 .sess_messages_number = messages_number,
131 .sess_recent_number = recent_number,
132 .sess_unseen_number = unseen_number,
133 .sess_list_folders = NULL,
134 .sess_lsub_folders = NULL,
135 .sess_subscribe_folder = NULL,
136 .sess_unsubscribe_folder = NULL,
137
138 .sess_append_message = append_message,
139 .sess_append_message_flags = append_message_flags,
140 .sess_copy_message = NULL,
141 .sess_move_message = NULL,
142
143 .sess_get_messages_list = get_messages_list,
144 .sess_get_envelopes_list = get_envelopes_list,
145 .sess_remove_message = NULL,
146#if 0
147 .sess_search_messages = maildriver_generic_search_messages,
148#endif
149
150 .sess_get_message = get_message,
151 .sess_get_message_by_uid = get_message_by_uid,
152};
153
154mailsession_driver * maildir_cached_session_driver =
155&local_maildir_cached_session_driver;
156
157
158static inline struct maildir_cached_session_state_data *
159get_cached_data(mailsession * session)
160{
161 return session->sess_data;
162}
163
164static inline mailsession * get_ancestor(mailsession * session)
165{
166 return get_cached_data(session)->md_ancestor;
167}
168
169static inline struct maildir_session_state_data *
170get_ancestor_data(mailsession * session)
171{
172 return get_ancestor(session)->sess_data;
173}
174
175
176static struct maildir * get_maildir_session(mailsession * session)
177{
178 return get_ancestor_data(session)->md_session;
179}
180
181static int initialize(mailsession * session)
182{
183 struct maildir_cached_session_state_data * data;
184
185 data = malloc(sizeof(* data));
186 if (data == NULL)
187 goto err;
188
189 data->md_ancestor = mailsession_new(maildir_session_driver);
190 if (data->md_ancestor == NULL)
191 goto free;
192
193 data->md_flags_store = mail_flags_store_new();
194 if (data->md_flags_store == NULL)
195 goto free_session;
196
197 data->md_quoted_mb = NULL;
198 data->md_cache_directory[0] = '\0';
199 data->md_flags_directory[0] = '\0';
200
201 session->sess_data = data;
202
203 return MAIL_NO_ERROR;
204
205 free_session:
206 mailsession_free(data->md_ancestor);
207 free:
208 free(data);
209 err:
210 return MAIL_ERROR_MEMORY;
211}
212
213static void
214free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data)
215{
216 if (maildir_cached_data->md_quoted_mb != NULL) {
217 free(maildir_cached_data->md_quoted_mb);
218 maildir_cached_data->md_quoted_mb = NULL;
219 }
220}
221
222static int
223write_cached_flags(struct mail_cache_db * cache_db,
224 MMAPString * mmapstr,
225 char * uid, struct mail_flags * flags);
226
227#define ENV_NAME "env.db"
228#define FLAGS_NAME "flags.db"
229
230static int flags_store_process(char * flags_directory, char * quoted_mb,
231 struct mail_flags_store * flags_store)
232{
233 char filename_flags[PATH_MAX];
234 struct mail_cache_db * cache_db_flags;
235 MMAPString * mmapstr;
236 unsigned int i;
237 int r;
238 int res;
239
240 if (carray_count(flags_store->fls_tab) == 0)
241 return MAIL_NO_ERROR;
242
243 if (quoted_mb == NULL)
244 return MAIL_NO_ERROR;
245
246 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
247 flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
248 MAIL_DIR_SEPARATOR, FLAGS_NAME);
249
250 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
251 if (r < 0) {
252 res = MAIL_ERROR_FILE;
253 goto err;
254 }
255
256 mmapstr = mmap_string_new("");
257 if (mmapstr == NULL) {
258 res = MAIL_ERROR_MEMORY;
259 goto close_db_flags;
260 }
261
262 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
263 mailmessage * msg;
264
265 msg = carray_get(flags_store->fls_tab, i);
266
267 r = write_cached_flags(cache_db_flags, mmapstr,
268 msg->msg_uid, msg->msg_flags);
269 if (r != MAIL_NO_ERROR) {
270 /* ignore errors */
271 }
272 }
273
274 mmap_string_free(mmapstr);
275 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
276
277 mail_flags_store_clear(flags_store);
278
279 return MAIL_NO_ERROR;
280
281 close_db_flags:
282 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
283 err:
284 return res;
285}
286
287static void uninitialize(mailsession * session)
288{
289 struct maildir_cached_session_state_data * data;
290
291 data = get_cached_data(session);
292
293 flags_store_process(data->md_flags_directory,
294 data->md_quoted_mb,
295 data->md_flags_store);
296
297 mail_flags_store_free(data->md_flags_store);
298 mailsession_free(data->md_ancestor);
299 free_quoted_mb(data);
300 free(data);
301
302 session->sess_data = data;
303}
304
305
306static int parameters(mailsession * session,
307 int id, void * value)
308{
309 struct maildir_cached_session_state_data * data;
310 int r;
311
312 data = get_cached_data(session);
313
314 switch (id) {
315 case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY:
316 strncpy(data->md_cache_directory, value, PATH_MAX);
317 data->md_cache_directory[PATH_MAX - 1] = '\0';
318
319 r = generic_cache_create_dir(data->md_cache_directory);
320 if (r != MAIL_NO_ERROR)
321 return r;
322
323 return MAIL_NO_ERROR;
324
325 case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY:
326 strncpy(data->md_flags_directory, value, PATH_MAX);
327 data->md_flags_directory[PATH_MAX - 1] = '\0';
328
329 r = generic_cache_create_dir(data->md_flags_directory);
330 if (r != MAIL_NO_ERROR)
331 return r;
332
333 return MAIL_NO_ERROR;
334
335 default:
336 return mailsession_parameters(data->md_ancestor, id, value);
337 }
338}
339
340
341static int get_cache_folder(mailsession * session, char ** result)
342{
343 struct maildir * md;
344 char * quoted_mb;
345 int res;
346 int r;
347 char key[PATH_MAX];
348 struct maildir_cached_session_state_data * data;
349
350 md = get_maildir_session(session);
351 data = get_cached_data(session);
352
353 quoted_mb = maildriver_quote_mailbox(md->mdir_path);
354 if (quoted_mb == NULL) {
355 res = MAIL_ERROR_MEMORY;
356 goto err;
357 }
358
359 snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb);
360 r = generic_cache_create_dir(key);
361 if (r != MAIL_NO_ERROR) {
362 res = r;
363 goto free_quoted_mb;
364 }
365
366 snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb);
367 r = generic_cache_create_dir(key);
368 if (r != MAIL_NO_ERROR) {
369 res = r;
370 goto free_quoted_mb;
371 }
372
373 * result = quoted_mb;
374
375 return MAIL_NO_ERROR;
376
377 free_quoted_mb:
378 free(quoted_mb);
379 err:
380 return res;
381}
382
383
384static int connect_path(mailsession * session, char * path)
385{
386 int r;
387 int res;
388 char * quoted_mb;
389
390 r = mailsession_connect_path(get_ancestor(session), path);
391 if (r != MAIL_NO_ERROR) {
392 res = r;
393 goto err;
394 }
395
396 r = get_cache_folder(session, &quoted_mb);
397 if (r != MAIL_NO_ERROR) {
398 res = r;
399 goto logout;
400 }
401
402 get_cached_data(session)->md_quoted_mb = quoted_mb;
403
404 return MAILDIR_NO_ERROR;
405
406 logout:
407 mailsession_logout(get_ancestor(session));
408 err:
409 return res;
410}
411
412static int logout(mailsession * session)
413{
414 struct maildir_cached_session_state_data * data;
415 int r;
416
417 data = get_cached_data(session);
418
419 flags_store_process(data->md_flags_directory,
420 data->md_quoted_mb, data->md_flags_store);
421
422 r = mailsession_logout(get_ancestor(session));
423 if (r != MAIL_NO_ERROR)
424 return r;
425
426 free_quoted_mb(get_cached_data(session));
427
428 return MAIL_NO_ERROR;
429}
430
431static int status_folder(mailsession * session, char * mb,
432 uint32_t * result_messages, uint32_t * result_recent,
433 uint32_t * result_unseen)
434{
435 return mailsession_status_folder(get_ancestor(session), mb,
436 result_messages, result_recent, result_unseen);
437}
438
439static int messages_number(mailsession * session, char * mb,
440 uint32_t * result)
441{
442 return mailsession_messages_number(get_ancestor(session), mb, result);
443}
444
445static int unseen_number(mailsession * session, char * mb,
446 uint32_t * result)
447{
448 return mailsession_unseen_number(get_ancestor(session), mb, result);
449}
450
451static int recent_number(mailsession * session, char * mb,
452 uint32_t * result)
453{
454 return mailsession_recent_number(get_ancestor(session), mb, result);
455}
456
457
458static int append_message(mailsession * session,
459 char * message, size_t size)
460{
461#if 0
462 return mailsession_append_message(get_ancestor(session), message, size);
463#endif
464 return append_message_flags(session, message, size, NULL);
465}
466
467static int append_message_flags(mailsession * session,
468 char * message, size_t size, struct mail_flags * flags)
469{
470 struct maildir * md;
471 int r;
472 char uid[PATH_MAX];
473 struct maildir_msg * md_msg;
474 chashdatum key;
475 chashdatum value;
476 uint32_t md_flags;
477 struct mail_cache_db * cache_db_flags;
478 char filename_flags[PATH_MAX];
479 MMAPString * mmapstr;
480 struct maildir_cached_session_state_data * data;
481
482 md = get_maildir_session(session);
483 if (md == NULL)
484 return MAIL_ERROR_BAD_STATE;
485
486 r = maildir_message_add_uid(md, message, size,
487 uid, sizeof(uid));
488 if (r != MAILDIR_NO_ERROR)
489 return maildirdriver_maildir_error_to_mail_error(r);
490
491 if (flags == NULL)
492 goto exit;
493
494 data = get_cached_data(session);
495
496 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
497 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
498 MAIL_DIR_SEPARATOR, FLAGS_NAME);
499
500 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
501 if (r < 0)
502 goto exit;
503
504 mmapstr = mmap_string_new("");
505 if (mmapstr == NULL)
506 goto close_db_flags;
507
508 r = write_cached_flags(cache_db_flags, mmapstr,
509 uid, flags);
510
511 mmap_string_free(mmapstr);
512 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
513
514 if (r != MAIL_NO_ERROR)
515 goto exit;
516
517 key.data = uid;
518 key.len = strlen(uid);
519 r = chash_get(md->mdir_msg_hash, &key, &value);
520 if (r < 0)
521 goto exit;
522
523 md_msg = value.data;
524
525 md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags);
526
527 r = maildir_message_change_flags(md, uid, md_flags);
528 if (r != MAILDIR_NO_ERROR)
529 goto exit;
530
531 return MAIL_NO_ERROR;
532
533 close_db_flags:
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535 exit:
536 return MAIL_NO_ERROR;
537}
538
539#define UID_NAME "uid.db"
540
541static int uid_clean_up(struct mail_cache_db * uid_db,
542 struct mailmessage_list * env_list)
543{
544 chash * hash_exist;
545 int res;
546 int r;
547 unsigned int i;
548 chashdatum key;
549 chashdatum value;
550 char key_str[PATH_MAX];
551
552 /* flush cache */
553
554 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
555 if (hash_exist == NULL) {
556 res = MAIL_ERROR_MEMORY;
557 goto err;
558 }
559
560 value.data = NULL;
561 value.len = 0;
562
563 key.data = "max-uid";
564 key.len = strlen("max-uid");
565 r = chash_set(hash_exist, &key, &value, NULL);
566
567 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
568 mailmessage * msg;
569
570 msg = carray_get(env_list->msg_tab, i);
571
572 value.data = NULL;
573 value.len = 0;
574
575 key.data = msg->msg_uid;
576 key.len = strlen(msg->msg_uid);
577 r = chash_set(hash_exist, &key, &value, NULL);
578 if (r < 0) {
579 res = MAIL_ERROR_MEMORY;
580 goto free;
581 }
582
583 snprintf(key_str, sizeof(key_str), "uid-%lu",
584 (unsigned long) msg->msg_index);
585 key.data = key_str;
586 key.len = strlen(key_str);
587 r = chash_set(hash_exist, &key, &value, NULL);
588 if (r < 0) {
589 res = MAIL_ERROR_MEMORY;
590 goto free;
591 }
592 }
593
594 mail_cache_db_clean_up(uid_db, hash_exist);
595
596 chash_free(hash_exist);
597
598 return MAIL_NO_ERROR;
599
600 free:
601 chash_free(hash_exist);
602 err:
603 return res;
604}
605
606static int get_messages_list(mailsession * session,
607 struct mailmessage_list ** result)
608{
609 struct maildir * md;
610 int r;
611 struct mailmessage_list * env_list;
612 int res;
613 uint32_t max_uid;
614 char filename[PATH_MAX];
615 struct mail_cache_db * uid_db;
616 void * value;
617 size_t value_len;
618 unsigned long i;
619 struct maildir_cached_session_state_data * data;
620 char key[PATH_MAX];
621
622 data = get_cached_data(session);
623
624 md = get_maildir_session(session);
625 if (md == NULL) {
626 res = MAIL_ERROR_BAD_STATE;
627 goto err;
628 }
629
630 check_folder(session);
631
632 r = maildir_update(md);
633 if (r != MAILDIR_NO_ERROR) {
634 res = maildirdriver_maildir_error_to_mail_error(r);
635 goto err;
636 }
637
638 r = maildir_get_messages_list(session, md,
639 maildir_cached_message_driver, &env_list);
640 if (r != MAILDIR_NO_ERROR) {
641 res = r;
642 goto err;
643 }
644
645 /* read/write DB */
646
647 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
648 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
649 MAIL_DIR_SEPARATOR, UID_NAME);
650
651 r = mail_cache_db_open_lock(filename, &uid_db);
652 if (r < 0) {
653 res = MAIL_ERROR_MEMORY;
654 goto free_list;
655 }
656
657 max_uid = 0;
658 r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1,
659 &value, &value_len);
660 if (r == 0) {
661 memcpy(&max_uid, value, sizeof(max_uid));
662 }
663
664 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
665 mailmessage * msg;
666 uint32_t index;
667
668 msg = carray_get(env_list->msg_tab, i);
669
670 r = mail_cache_db_get(uid_db, msg->msg_uid,
671 strlen(msg->msg_uid), &value, &value_len);
672 if (r < 0) {
673 max_uid ++;
674 msg->msg_index = max_uid;
675 mail_cache_db_put(uid_db, msg->msg_uid,
676 strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index));
677
678 snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index);
679 mail_cache_db_put(uid_db, key, strlen(key),
680 msg->msg_uid, strlen(msg->msg_uid));
681 }
682 else {
683 memcpy(&index, value, sizeof(index));
684 msg->msg_index = index;
685 }
686 }
687
688 mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1,
689 &max_uid, sizeof(max_uid));
690
691 uid_clean_up(uid_db, env_list);
692
693 mail_cache_db_close_unlock(filename, uid_db);
694
695 * result = env_list;
696
697 return MAIL_NO_ERROR;
698
699 free_list:
700 mailmessage_list_free(env_list);
701 err:
702 return res;
703}
704
705static int
706get_cached_flags(struct mail_cache_db * cache_db,
707 MMAPString * mmapstr,
708 mailsession * session,
709 char * uid,
710 struct mail_flags ** result)
711{
712 int r;
713 char keyname[PATH_MAX];
714 struct mail_flags * flags;
715 int res;
716
717 snprintf(keyname, PATH_MAX, "%s-flags", uid);
718
719 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
720 if (r != MAIL_NO_ERROR) {
721 res = r;
722 goto err;
723 }
724
725 * result = flags;
726
727 return MAIL_NO_ERROR;
728
729 err:
730 return res;
731}
732
733static int
734get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
735 mailsession * session, char * uid,
736 struct mailimf_fields ** result)
737{
738 int r;
739 char keyname[PATH_MAX];
740 struct mailimf_fields * fields;
741 int res;
742
743 snprintf(keyname, PATH_MAX, "%s-envelope", uid);
744
745 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
746 if (r != MAIL_NO_ERROR) {
747 res = r;
748 goto err;
749 }
750
751 * result = fields;
752
753 return MAIL_NO_ERROR;
754
755 err:
756 return res;
757}
758
759static int
760write_cached_envelope(struct mail_cache_db * cache_db,
761 MMAPString * mmapstr,
762 mailsession * session, char * uid,
763 struct mailimf_fields * fields)
764{
765 int r;
766 char keyname[PATH_MAX];
767 int res;
768
769 snprintf(keyname, PATH_MAX, "%s-envelope", uid);
770
771 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
772 if (r != MAIL_NO_ERROR) {
773 res = r;
774 goto err;
775 }
776
777 return MAIL_NO_ERROR;
778
779 err:
780 return res;
781}
782
783static int
784write_cached_flags(struct mail_cache_db * cache_db,
785 MMAPString * mmapstr,
786 char * uid, struct mail_flags * flags)
787{
788 int r;
789 char keyname[PATH_MAX];
790 int res;
791
792 snprintf(keyname, PATH_MAX, "%s-flags", uid);
793
794 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
795 if (r != MAIL_NO_ERROR) {
796 res = r;
797 goto err;
798 }
799
800 return MAIL_NO_ERROR;
801
802 err:
803 return res;
804}
805
806
807static int get_envelopes_list(mailsession * session,
808 struct mailmessage_list * env_list)
809{
810 int r;
811 unsigned int i;
812 int res;
813 struct maildir_cached_session_state_data * data;
814 char filename_env[PATH_MAX];
815 char filename_flags[PATH_MAX];
816 struct mail_cache_db * cache_db_env;
817 struct mail_cache_db * cache_db_flags;
818 MMAPString * mmapstr;
819
820 data = get_cached_data(session);
821
822 flags_store_process(data->md_flags_directory,
823 data->md_quoted_mb, data->md_flags_store);
824
825 mmapstr = mmap_string_new("");
826 if (mmapstr == NULL) {
827 res = MAIL_ERROR_MEMORY;
828 goto err;
829 }
830
831 snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
832 data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
833 MAIL_DIR_SEPARATOR, ENV_NAME);
834
835 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
836 if (r < 0) {
837 res = MAIL_ERROR_MEMORY;
838 goto free_mmapstr;
839 }
840
841 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
842 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
843 MAIL_DIR_SEPARATOR, FLAGS_NAME);
844
845 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
846 if (r < 0) {
847 res = MAIL_ERROR_FILE;
848 goto close_db_env;
849 }
850
851 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) {
852 mailmessage * msg;
853 struct mailimf_fields * fields;
854 struct mail_flags * flags;
855
856 msg = carray_get(env_list->msg_tab, i);
857
858 if (msg->msg_fields == NULL) {
859 r = get_cached_envelope(cache_db_env, mmapstr, session,
860 msg->msg_uid, &fields);
861 if (r == MAIL_NO_ERROR) {
862 msg->msg_cached = TRUE;
863 msg->msg_fields = fields;
864 }
865 }
866
867 if (msg->msg_flags == NULL) {
868 r = get_cached_flags(cache_db_flags, mmapstr,
869 session, msg->msg_uid, &flags);
870 if (r == MAIL_NO_ERROR) {
871 msg->msg_flags = flags;
872 }
873 }
874 }
875
876 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
877 mail_cache_db_close_unlock(filename_env, cache_db_env);
878
879 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
880 if (r != MAIL_NO_ERROR) {
881 res = r;
882 goto free_mmapstr;
883 }
884
885 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
886 if (r < 0) {
887 res = MAIL_ERROR_MEMORY;
888 goto free_mmapstr;
889 }
890
891 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
892 if (r < 0) {
893 res = MAIL_ERROR_FILE;
894 goto close_db_env;
895 }
896
897 /* must write cache */
898
899 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
900 mailmessage * msg;
901
902 msg = carray_get(env_list->msg_tab, i);
903
904 if (msg->msg_fields != NULL) {
905 if (!msg->msg_cached) {
906 /* msg->index is the numerical UID of the message */
907 r = write_cached_envelope(cache_db_env, mmapstr,
908 session, msg->msg_uid, msg->msg_fields);
909 }
910 }
911
912 if (msg->msg_flags != NULL) {
913 r = write_cached_flags(cache_db_flags, mmapstr,
914 msg->msg_uid, msg->msg_flags);
915 }
916 }
917
918 /* flush cache */
919
920 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
921
922 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
923 mail_cache_db_close_unlock(filename_env, cache_db_env);
924
925 mmap_string_free(mmapstr);
926
927 return MAIL_NO_ERROR;
928
929 close_db_env:
930 mail_cache_db_close_unlock(filename_env, cache_db_env);
931 free_mmapstr:
932 mmap_string_free(mmapstr);
933 err:
934 return res;
935}
936
937static int expunge_folder(mailsession * session)
938{
939 return mailsession_expunge_folder(get_ancestor(session));
940}
941
942static int check_folder(mailsession * session)
943{
944 struct maildir_cached_session_state_data * data;
945
946 data = get_cached_data(session);
947
948 flags_store_process(data->md_flags_directory,
949 data->md_quoted_mb, data->md_flags_store);
950
951 return mailsession_check_folder(get_ancestor(session));
952}
953
954static int get_message(mailsession * session,
955 uint32_t num, mailmessage ** result)
956{
957 struct maildir * md;
958 int res;
959 mailmessage * msg;
960 char filename[PATH_MAX];
961 struct mail_cache_db * uid_db;
962 char * msg_filename;
963 struct stat stat_info;
964 char key_str[PATH_MAX];
965 void * value;
966 size_t value_len;
967 char uid[PATH_MAX];
968 struct maildir_cached_session_state_data * data;
969 int r;
970
971 data = get_cached_data(session);
972
973 md = get_maildir_session(session);
974
975 /* a get_messages_list() should have been done once before */
976
977 /* read DB */
978
979 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
980 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
981 MAIL_DIR_SEPARATOR, UID_NAME);
982
983 r = mail_cache_db_open_lock(filename, &uid_db);
984 if (r < 0) {
985 res = MAIL_ERROR_MEMORY;
986 goto err;
987 }
988
989 snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num);
990
991 r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len);
992 if (r < 0) {
993 res = MAIL_ERROR_INVAL;
994 goto close_db;
995 }
996
997 if (value_len >= PATH_MAX) {
998 res = MAIL_ERROR_INVAL;
999 goto close_db;
1000 }
1001
1002 memcpy(uid, value, value_len);
1003 uid[value_len] = '\0';
1004
1005 mail_cache_db_close_unlock(filename, uid_db);
1006
1007 /* update maildir data */
1008
1009 r = maildir_update(md);
1010 if (r != MAILDIR_NO_ERROR) {
1011 res = maildirdriver_maildir_error_to_mail_error(r);
1012 goto err;
1013 }
1014
1015 msg_filename = maildir_message_get(md, uid);
1016 if (msg_filename == NULL) {
1017 res = MAIL_ERROR_INVAL;
1018 goto err;
1019 }
1020
1021 r = stat(msg_filename, &stat_info);
1022 free(msg_filename);
1023 if (r < 0) {
1024 res = MAIL_ERROR_INVAL;
1025 goto err;
1026 }
1027
1028 /* create message */
1029
1030 msg = mailmessage_new();
1031 if (msg == NULL) {
1032 res = MAIL_ERROR_MEMORY;
1033 goto err;
1034 }
1035
1036 r = mailmessage_init(msg, session, maildir_cached_message_driver,
1037 num, stat_info.st_size);
1038 if (r != MAIL_NO_ERROR) {
1039 mailmessage_free(msg);
1040 res = r;
1041 goto err;
1042 }
1043
1044 msg->msg_uid = strdup(uid);
1045 if (msg->msg_uid == NULL) {
1046 mailmessage_free(msg);
1047 res = r;
1048 goto err;
1049 }
1050
1051 * result = msg;
1052
1053 return MAIL_NO_ERROR;
1054
1055 close_db:
1056 mail_cache_db_close_unlock(filename, uid_db);
1057 err:
1058 return res;
1059}
1060
1061
1062static int get_message_by_uid(mailsession * session,
1063 const char * uid, mailmessage ** result)
1064{
1065 int r;
1066 struct maildir * md;
1067 int res;
1068 mailmessage * msg;
1069 char filename[PATH_MAX];
1070 struct mail_cache_db * uid_db;
1071 char * msg_filename;
1072 struct stat stat_info;
1073 void * value;
1074 size_t value_len;
1075 struct maildir_cached_session_state_data * data;
1076 uint32_t index;
1077
1078 data = get_cached_data(session);
1079
1080 md = get_maildir_session(session);
1081
1082 /* a get_messages_list() should have been done once before */
1083
1084 /* read DB */
1085
1086 snprintf(filename, sizeof(filename), "%s%c%s%c%s",
1087 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
1088 MAIL_DIR_SEPARATOR, UID_NAME);
1089
1090 r = mail_cache_db_open_lock(filename, &uid_db);
1091 if (r < 0) {
1092 res = MAIL_ERROR_MEMORY;
1093 goto err;
1094 }
1095
1096 r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len);
1097 if (r < 0) {
1098 res = MAIL_ERROR_INVAL;
1099 goto close_db;
1100 }
1101
1102 memcpy(&index, value, sizeof(index));
1103
1104 mail_cache_db_close_unlock(filename, uid_db);
1105
1106 /* update maildir data */
1107
1108 r = maildir_update(md);
1109 if (r != MAILDIR_NO_ERROR) {
1110 res = maildirdriver_maildir_error_to_mail_error(r);
1111 goto err;
1112 }
1113
1114 msg_filename = maildir_message_get(md, uid);
1115 if (msg_filename == NULL) {
1116 res = MAIL_ERROR_INVAL;
1117 goto err;
1118 }
1119
1120 r = stat(msg_filename, &stat_info);
1121 free(msg_filename);
1122 if (r < 0) {
1123 res = MAIL_ERROR_INVAL;
1124 goto err;
1125 }
1126
1127 /* create message */
1128
1129 msg = mailmessage_new();
1130 if (msg == NULL) {
1131 res = MAIL_ERROR_MEMORY;
1132 goto err;
1133 }
1134
1135 r = mailmessage_init(msg, session, maildir_cached_message_driver,
1136 index, stat_info.st_size);
1137 if (r != MAIL_NO_ERROR) {
1138 mailmessage_free(msg);
1139 res = r;
1140 goto err;
1141 }
1142
1143 msg->msg_uid = strdup(uid);
1144 if (msg->msg_uid == NULL) {
1145 mailmessage_free(msg);
1146 res = r;
1147 goto err;
1148 }
1149
1150 * result = msg;
1151
1152 return MAIL_NO_ERROR;
1153
1154 close_db:
1155 mail_cache_db_close_unlock(filename, uid_db);
1156 err:
1157 return res;
1158}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h
new file mode 100644
index 0000000..5c3d8a9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_H
37
38#define MAILDIRDRIVER_CACHED_H
39
40#include <libetpan/maildriver.h>
41#include <libetpan/maildirdriver_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47extern mailsession_driver * maildir_cached_session_driver;
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c
new file mode 100644
index 0000000..d2c30cc
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c
@@ -0,0 +1,334 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "maildirdriver.h"
40#include "maildir.h"
41#include "generic_cache.h"
42#include "mail_cache_db.h"
43#include "maildirdriver_tools.h"
44
45#include <unistd.h>
46#include <sys/mman.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50#include <string.h>
51#include <stdlib.h>
52
53static int get_flags(mailmessage * msg_info,
54 struct mail_flags ** result);
55
56static int prefetch(mailmessage * msg_info);
57
58static void prefetch_free(struct generic_message_t * msg);
59
60static int initialize(mailmessage * msg_info);
61
62static void check(mailmessage * msg_info);
63
64static mailmessage_driver local_maildir_cached_message_driver = {
65 .msg_name = "maildir-cached",
66
67 .msg_initialize = initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = check,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mailmessage_generic_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_header,
78 .msg_fetch_size = NULL,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = get_flags,
87};
88
89mailmessage_driver * maildir_cached_message_driver =
90&local_maildir_cached_message_driver;
91
92struct maildir_msg_data {
93 int fd;
94};
95
96#if 0
97static inline struct maildir_cached_session_state_data *
98get_cached_session_data(mailmessage * msg)
99{
100 return msg->session->data;
101}
102
103static inline mailsession * cached_session_get_ancestor(mailsession * session)
104{
105 return get_data(session)->session;
106}
107
108static inline struct maildir_session_state_data *
109cached_session_get_ancestor_data(mailsession * session)
110{
111 return get_ancestor(session)->data;
112}
113
114static struct maildir * get_maildir_session(mailmessage * msg)
115{
116 return cached_session_get_ancestor_data(msg->session)->session;
117}
118#endif
119static inline struct maildir_cached_session_state_data *
120get_cached_session_data(mailmessage * msg)
121{
122 return msg->msg_session->sess_data;
123}
124
125static inline struct maildir_cached_session_state_data *
126cached_session_get_data(mailsession * s)
127{
128 return s->sess_data;
129}
130
131static inline mailsession * cached_session_get_ancestor(mailsession * s)
132{
133 return cached_session_get_data(s)->md_ancestor;
134}
135
136static inline struct maildir_session_state_data *
137cached_session_get_ancestor_data(mailsession * s)
138{
139 return cached_session_get_ancestor(s)->sess_data;
140}
141
142static inline struct maildir_session_state_data *
143get_session_ancestor_data(mailmessage * msg)
144{
145 return cached_session_get_ancestor_data(msg->msg_session);
146}
147
148static inline struct maildir *
149cached_session_get_maildir_session(mailsession * session)
150{
151 return cached_session_get_ancestor_data(session)->md_session;
152}
153
154static inline struct maildir * get_maildir_session(mailmessage * msg)
155{
156 return cached_session_get_maildir_session(msg->msg_session);
157}
158
159static int prefetch(mailmessage * msg_info)
160{
161 struct generic_message_t * msg;
162 int res;
163 struct maildir_msg_data * data;
164 char * filename;
165 int fd;
166 char * mapping;
167 struct maildir * md;
168
169 md = get_maildir_session(msg_info);
170
171 filename = maildir_message_get(md, msg_info->msg_uid);
172 if (filename == NULL) {
173 res = MAIL_ERROR_MEMORY;
174 goto err;
175 }
176
177 fd = open(filename, O_RDONLY);
178 free(filename);
179 if (fd == -1) {
180 res = MAIL_ERROR_FILE;
181 goto err;
182 }
183
184 mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
185 if (mapping == MAP_FAILED) {
186 res = MAIL_ERROR_FILE;
187 goto close;
188 }
189
190 data = malloc(sizeof(* data));
191 if (data == NULL) {
192 res = MAIL_ERROR_MEMORY;
193 goto unmap;
194 }
195
196 data->fd = fd;
197
198 msg = msg_info->msg_data;
199
200 msg->msg_data = data;
201 msg->msg_message = mapping;
202 msg->msg_length = msg_info->msg_size;
203
204 return MAIL_NO_ERROR;
205
206 unmap:
207 munmap(mapping, msg_info->msg_size);
208 close:
209 close(fd);
210 err:
211 return res;
212}
213
214static void prefetch_free(struct generic_message_t * msg)
215{
216 if (msg->msg_message != NULL) {
217 struct maildir_msg_data * data;
218
219 munmap(msg->msg_message, msg->msg_length);
220 msg->msg_message = NULL;
221 data = msg->msg_data;
222 close(data->fd);
223 free(data);
224 }
225}
226
227static int initialize(mailmessage * msg_info)
228{
229 struct generic_message_t * msg;
230 int r;
231
232 r = mailmessage_generic_initialize(msg_info);
233 if (r != MAIL_NO_ERROR)
234 return r;
235
236 msg = msg_info->msg_data;
237 msg->msg_prefetch = prefetch;
238 msg->msg_prefetch_free = prefetch_free;
239
240 return MAIL_NO_ERROR;
241}
242
243static void check(mailmessage * msg_info)
244{
245 int r;
246
247 if (msg_info->msg_flags != NULL) {
248 r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info);
249
250 r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info);
251 /* ignore errors */
252 }
253}
254
255#define FLAGS_NAME "flags.db"
256
257static int get_flags(mailmessage * msg_info,
258 struct mail_flags ** result)
259{
260 struct mail_cache_db * cache_db_flags;
261 chashdatum key;
262 chashdatum value;
263 struct maildir * md;
264 struct mail_flags * flags;
265 struct maildir_cached_session_state_data * data;
266 struct maildir_msg * md_msg;
267 int r;
268 uint32_t driver_flags;
269 char filename_flags[PATH_MAX];
270 char keyname[PATH_MAX];
271 MMAPString * mmapstr;
272
273 if (msg_info->msg_flags != NULL) {
274 * result = msg_info->msg_flags;
275 return MAIL_NO_ERROR;
276 }
277
278 data = get_cached_session_data(msg_info);
279 flags = mail_flags_store_get(data->md_flags_store,
280 msg_info->msg_index);
281 if (flags != NULL) {
282 msg_info->msg_flags = flags;
283 * result = msg_info->msg_flags;
284 return MAIL_NO_ERROR;
285 }
286
287 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
288 data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb,
289 MAIL_DIR_SEPARATOR, FLAGS_NAME);
290
291 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
292 if (r < 0)
293 return MAIL_ERROR_FILE;
294
295 snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid);
296
297 mmapstr = mmap_string_new("");
298 if (mmapstr == NULL) {
299 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
300 return MAIL_ERROR_MEMORY;
301 }
302
303 r = generic_cache_flags_read(cache_db_flags, mmapstr, keyname, &flags);
304 mmap_string_free(mmapstr);
305
306 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
307
308 if (r != MAIL_NO_ERROR) {
309 flags = mail_flags_new_empty();
310 if (flags == NULL)
311 return MAIL_ERROR_MEMORY;
312 }
313
314 md = get_maildir_session(msg_info);
315 if (md == NULL)
316 return MAIL_ERROR_BAD_STATE;
317
318 key.data = msg_info->msg_uid;
319 key.len = strlen(msg_info->msg_uid);
320 r = chash_get(md->mdir_msg_hash, &key, &value);
321 if (r < 0)
322 return MAIL_ERROR_MSG_NOT_FOUND;
323
324 md_msg = value.data;
325
326 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
327
328 flags->fl_flags = driver_flags;
329 msg_info->msg_flags = flags;
330
331 * result = msg_info->msg_flags;
332
333 return MAIL_NO_ERROR;
334}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h
new file mode 100644
index 0000000..b9e0215
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H
37
38#define MAILDIRDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_message.c b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
new file mode 100644
index 0000000..58bc6bd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
@@ -0,0 +1,255 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver_message.h"
37#include "maildirdriver_tools.h"
38
39#include "mailmessage_tools.h"
40#include "maildirdriver.h"
41#include "maildir.h"
42#include "generic_cache.h"
43
44#include <unistd.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <fcntl.h>
49#include <string.h>
50#include <stdlib.h>
51
52static int get_flags(mailmessage * msg_info,
53 struct mail_flags ** result);
54
55static int prefetch(mailmessage * msg_info);
56
57static void prefetch_free(struct generic_message_t * msg);
58
59static int initialize(mailmessage * msg_info);
60
61static void check(mailmessage * msg_info);
62
63static mailmessage_driver local_maildir_message_driver = {
64 .msg_name = "maildir",
65
66 .msg_initialize = initialize,
67 .msg_uninitialize = mailmessage_generic_uninitialize,
68
69 .msg_flush = mailmessage_generic_flush,
70 .msg_check = check,
71
72 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
73
74 .msg_fetch = mailmessage_generic_fetch,
75 .msg_fetch_header = mailmessage_generic_fetch_header,
76 .msg_fetch_body = mailmessage_generic_fetch_header,
77 .msg_fetch_size = NULL,
78 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
79 .msg_fetch_section = mailmessage_generic_fetch_section,
80 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
81 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
82 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
83 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
84
85 .msg_get_flags = get_flags,
86};
87
88mailmessage_driver * maildir_message_driver = &local_maildir_message_driver;
89
90struct maildir_msg_data {
91 int fd;
92};
93
94static inline struct maildir_session_state_data *
95get_session_data(mailmessage * msg)
96{
97 return msg->msg_session->sess_data;
98}
99
100static struct maildir * get_maildir_session(mailmessage * msg)
101{
102 return get_session_data(msg)->md_session;
103}
104
105static int prefetch(mailmessage * msg_info)
106{
107 struct generic_message_t * msg;
108 int res;
109 struct maildir_msg_data * data;
110 char * filename;
111 int fd;
112 char * mapping;
113 struct maildir * md;
114
115 md = get_maildir_session(msg_info);
116
117 if (msg_info->msg_uid == NULL) {
118 res = MAIL_ERROR_INVAL;
119 goto err;
120 }
121
122 filename = maildir_message_get(md, msg_info->msg_uid);
123 if (filename == NULL) {
124 res = MAIL_ERROR_MEMORY;
125 goto err;
126 }
127
128 fd = open(filename, O_RDONLY);
129 free(filename);
130 if (fd == -1) {
131 res = MAIL_ERROR_FILE;
132 goto err;
133 }
134
135 mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
136 if (mapping == MAP_FAILED) {
137 res = MAIL_ERROR_FILE;
138 goto close;
139 }
140
141 data = malloc(sizeof(* data));
142 if (data == NULL) {
143 res = MAIL_ERROR_MEMORY;
144 goto unmap;
145 }
146
147 data->fd = fd;
148
149 msg = msg_info->msg_data;
150
151 msg->msg_data = data;
152 msg->msg_message = mapping;
153 msg->msg_length = msg_info->msg_size;
154
155 return MAIL_NO_ERROR;
156
157 unmap:
158 munmap(mapping, msg_info->msg_size);
159 close:
160 close(fd);
161 err:
162 return res;
163}
164
165static void prefetch_free(struct generic_message_t * msg)
166{
167 if (msg->msg_message != NULL) {
168 struct maildir_msg_data * data;
169
170 munmap(msg->msg_message, msg->msg_length);
171 msg->msg_message = NULL;
172 data = msg->msg_data;
173 close(data->fd);
174 free(data);
175 }
176}
177
178static int initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182
183 r = mailmessage_generic_initialize(msg_info);
184 if (r != MAIL_NO_ERROR)
185 return r;
186
187 msg = msg_info->msg_data;
188 msg->msg_prefetch = prefetch;
189 msg->msg_prefetch_free = prefetch_free;
190
191 return MAIL_NO_ERROR;
192}
193
194static void check(mailmessage * msg_info)
195{
196 int r;
197
198 if (msg_info->msg_flags != NULL) {
199 r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store,
200 msg_info);
201 /* ignore errors */
202 }
203}
204
205static int get_flags(mailmessage * msg_info,
206 struct mail_flags ** result)
207{
208 chashdatum key;
209 chashdatum value;
210 struct maildir * md;
211 struct mail_flags * flags;
212 struct maildir_session_state_data * data;
213 struct maildir_msg * md_msg;
214 int r;
215 uint32_t driver_flags;
216 clist * ext;
217
218 if (msg_info->msg_flags != NULL) {
219 * result = msg_info->msg_flags;
220 return MAIL_NO_ERROR;
221 }
222
223 data = get_session_data(msg_info);
224 flags = mail_flags_store_get(data->md_flags_store,
225 msg_info->msg_index);
226 if (flags != NULL) {
227 msg_info->msg_flags = flags;
228 * result = msg_info->msg_flags;
229 return MAIL_NO_ERROR;
230 }
231
232 md = get_maildir_session(msg_info);
233 if (md == NULL)
234 return MAIL_ERROR_BAD_STATE;
235
236 key.data = msg_info->msg_uid;
237 key.len = strlen(msg_info->msg_uid);
238 r = chash_get(md->mdir_msg_hash, &key, &value);
239 if (r < 0)
240 return MAIL_ERROR_MSG_NOT_FOUND;
241
242 md_msg = value.data;
243
244 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
245
246 ext = clist_new();
247 if (ext == NULL)
248 return MAIL_ERROR_MEMORY;
249
250 msg_info->msg_flags = mail_flags_new(driver_flags, ext);
251
252 * result = msg_info->msg_flags;
253
254 return MAIL_NO_ERROR;
255}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_message.h b/libetpan/src/driver/implementation/maildir/maildirdriver_message.h
new file mode 100644
index 0000000..ed0a4d1
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_MESSAGE_H
37
38#define MAILDIRDRIVER_MESSAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * maildir_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c
new file mode 100644
index 0000000..e3036e8
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c
@@ -0,0 +1,198 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage.h"
37#include "maildirdriver_tools.h"
38#include "maildir.h"
39#include "generic_cache.h"
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <stdlib.h>
43#include <string.h>
44
45int maildirdriver_maildir_error_to_mail_error(int error)
46{
47 switch (error) {
48 case MAILDIR_NO_ERROR:
49 return MAIL_NO_ERROR;
50
51 case MAILDIR_ERROR_CREATE:
52 return MAIL_ERROR_FILE;
53
54 case MAILDIR_ERROR_DIRECTORY:
55 return MAIL_ERROR_FILE;
56
57 case MAILDIR_ERROR_MEMORY:
58 return MAIL_ERROR_MEMORY;
59
60 case MAILDIR_ERROR_FILE:
61 return MAIL_ERROR_FILE;
62
63 case MAILDIR_ERROR_FOLDER:
64 return MAIL_ERROR_FOLDER;
65
66 case MAILDIR_ERROR_NOT_FOUND:
67 return MAIL_ERROR_MSG_NOT_FOUND;
68
69 default:
70 return MAIL_ERROR_INVAL;
71 }
72}
73
74
75
76uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags)
77{
78 uint32_t flags;
79
80 flags = 0;
81 if ((md_flags & MAILDIR_FLAG_NEW) != 0)
82 flags |= MAIL_FLAG_NEW;
83
84 if ((md_flags & MAILDIR_FLAG_SEEN) != 0)
85 flags |= MAIL_FLAG_SEEN;
86
87 if ((md_flags & MAILDIR_FLAG_REPLIED) != 0)
88 flags |= MAIL_FLAG_ANSWERED;
89
90 if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0)
91 flags |= MAIL_FLAG_FLAGGED;
92
93 if ((md_flags & MAILDIR_FLAG_TRASHED) != 0)
94 flags |= MAIL_FLAG_DELETED;
95
96 return flags;
97}
98
99uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags)
100{
101 uint32_t md_flags;
102
103 md_flags = 0;
104 if ((flags & MAIL_FLAG_NEW) != 0)
105 md_flags |= MAILDIR_FLAG_NEW;
106
107 if ((flags & MAIL_FLAG_SEEN) != 0)
108 md_flags |= MAILDIR_FLAG_SEEN;
109
110 if ((flags & MAIL_FLAG_ANSWERED) != 0)
111 md_flags |= MAILDIR_FLAG_REPLIED;
112
113 if ((flags & MAIL_FLAG_FLAGGED) != 0)
114 md_flags |= MAILDIR_FLAG_FLAGGED;
115
116 if ((flags & MAIL_FLAG_DELETED) != 0)
117 md_flags |= MAILDIR_FLAG_TRASHED;
118
119 return md_flags;
120}
121
122
123int maildir_get_messages_list(mailsession * session, struct maildir * md,
124 mailmessage_driver * message_driver,
125 struct mailmessage_list ** result)
126{
127 unsigned int i;
128 struct mailmessage_list * env_list;
129 int r;
130 carray * tab;
131 int res;
132
133 tab = carray_new(128);
134 if (tab == NULL) {
135 res = MAIL_ERROR_MEMORY;
136 goto err;
137 }
138
139 for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) {
140 struct maildir_msg * md_msg;
141 mailmessage * msg;
142 char * filename;
143 struct stat stat_info;
144
145 md_msg = carray_get(md->mdir_msg_list, i);
146
147 filename = maildir_message_get(md, md_msg->msg_uid);
148 r = stat(filename, &stat_info);
149 free(filename);
150 if (r < 0)
151 continue;
152
153 msg = mailmessage_new();
154 if (msg == NULL) {
155 res = MAIL_ERROR_MEMORY;
156 goto free_list;
157 }
158
159 r = mailmessage_init(msg, session, message_driver,
160 i + 1, stat_info.st_size);
161 if (r != MAIL_NO_ERROR) {
162 mailmessage_free(msg);
163 res = r;
164 goto free_list;
165 }
166
167 msg->msg_uid = strdup(md_msg->msg_uid);
168 if (msg->msg_uid == NULL) {
169 mailmessage_free(msg);
170 res = MAIL_ERROR_MEMORY;
171 goto free_list;
172 }
173
174 r = carray_add(tab, msg, NULL);
175 if (r < 0) {
176 mailmessage_free(msg);
177 res = MAIL_ERROR_MEMORY;
178 goto free_list;
179 }
180 }
181
182 env_list = mailmessage_list_new(tab);
183 if (env_list == NULL) {
184 res = MAIL_ERROR_MEMORY;
185 goto free_list;
186 }
187
188 * result = env_list;
189
190 return MAIL_NO_ERROR;
191
192 free_list:
193 for(i = 0 ; i < carray_count(tab) ; i ++)
194 mailmessage_free(carray_get(tab, i));
195 carray_free(tab);
196 err:
197 return res;
198}
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h
new file mode 100644
index 0000000..0a738c9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_TOOLS_H
37
38#define MAILDIRDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "maildir.h"
42
43int maildirdriver_maildir_error_to_mail_error(int error);
44
45uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags);
46
47uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags);
48
49int maildir_get_messages_list(mailsession * session, struct maildir * md,
50 mailmessage_driver * message_driver,
51 struct mailmessage_list ** result);
52
53#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_types.h b/libetpan/src/driver/implementation/maildir/maildirdriver_types.h
new file mode 100644
index 0000000..c965b3e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_types.h
@@ -0,0 +1,96 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRDRIVER_TYPES_H
37
38#define MAILDIRDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/maildir.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51struct maildir_session_state_data {
52 struct maildir * md_session;
53 struct mail_flags_store * md_flags_store;
54};
55
56enum {
57 MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
58 MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
59};
60
61struct maildir_cached_session_state_data {
62 mailsession * md_ancestor;
63 char * md_quoted_mb;
64 struct mail_flags_store * md_flags_store;
65 char md_cache_directory[PATH_MAX];
66 char md_flags_directory[PATH_MAX];
67};
68
69/* maildir storage */
70
71/*
72 maildir_mailstorage is the state data specific to the maildir storage.
73
74 - pathname is the path of the maildir storage.
75
76 - cached if this value is != 0, a persistant cache will be
77 stored on local system.
78
79 - cache_directory is the location of the cache.
80
81 - flags_directory is the location of the flags.
82*/
83
84struct maildir_mailstorage {
85 char * md_pathname;
86
87 int md_cached;
88 char * md_cache_directory;
89 char * md_flags_directory;
90};
91
92#ifdef __cplusplus
93}
94#endif
95
96#endif
diff --git a/libetpan/src/driver/implementation/maildir/maildirstorage.c b/libetpan/src/driver/implementation/maildir/maildirstorage.c
new file mode 100644
index 0000000..09f95c7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirstorage.c
@@ -0,0 +1,193 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirstorage.h"
37#include "mailstorage.h"
38
39#include "mail.h"
40#include "mailmessage.h"
41#include "maildirdriver.h"
42#include "maildirdriver_cached.h"
43#include "maildriver.h"
44
45#include <stdlib.h>
46#include <string.h>
47
48/* maildir storage */
49
50static int maildir_mailstorage_connect(struct mailstorage * storage);
51static int
52maildir_mailstorage_get_folder_session(struct mailstorage * storage,
53 char * pathname, mailsession ** result);
54static void maildir_mailstorage_uninitialize(struct mailstorage * storage);
55
56static mailstorage_driver maildir_mailstorage_driver = {
57 .sto_name = "maildir",
58 .sto_connect = maildir_mailstorage_connect,
59 .sto_get_folder_session = maildir_mailstorage_get_folder_session,
60 .sto_uninitialize = maildir_mailstorage_uninitialize,
61};
62
63int maildir_mailstorage_init(struct mailstorage * storage,
64 char * md_pathname, int md_cached,
65 char * md_cache_directory, char * md_flags_directory)
66{
67 struct maildir_mailstorage * maildir_storage;
68
69 maildir_storage = malloc(sizeof(* maildir_storage));
70 if (maildir_storage == NULL)
71 goto err;
72
73 maildir_storage->md_pathname = strdup(md_pathname);
74 if (maildir_storage->md_pathname == NULL)
75 goto free;
76
77 maildir_storage->md_cached = md_cached;
78
79 if (md_cached && (md_cache_directory != NULL) &&
80 (md_flags_directory != NULL)) {
81 maildir_storage->md_cache_directory = strdup(md_cache_directory);
82 if (maildir_storage->md_cache_directory == NULL)
83 goto free_pathname;
84
85 maildir_storage->md_flags_directory = strdup(md_flags_directory);
86 if (maildir_storage->md_flags_directory == NULL)
87 goto free_cache_directory;
88 }
89 else {
90 maildir_storage->md_cached = FALSE;
91 maildir_storage->md_cache_directory = NULL;
92 maildir_storage->md_flags_directory = NULL;
93 }
94
95 storage->sto_data = maildir_storage;
96 storage->sto_driver = &maildir_mailstorage_driver;
97
98 return MAIL_NO_ERROR;
99
100 free_cache_directory:
101 free(maildir_storage->md_cache_directory);
102 free_pathname:
103 free(maildir_storage->md_pathname);
104 free:
105 free(maildir_storage);
106 err:
107 return MAIL_ERROR_MEMORY;
108}
109
110static void maildir_mailstorage_uninitialize(struct mailstorage * storage)
111{
112 struct maildir_mailstorage * maildir_storage;
113
114 maildir_storage = storage->sto_data;
115 if (maildir_storage->md_flags_directory != NULL)
116 free(maildir_storage->md_flags_directory);
117 if (maildir_storage->md_cache_directory != NULL)
118 free(maildir_storage->md_cache_directory);
119 free(maildir_storage->md_pathname);
120 free(maildir_storage);
121
122 storage->sto_data = NULL;
123}
124
125static int maildir_mailstorage_connect(struct mailstorage * storage)
126{
127 struct maildir_mailstorage * maildir_storage;
128 mailsession_driver * driver;
129 int r;
130 int res;
131 mailsession * session;
132
133 maildir_storage = storage->sto_data;
134
135 if (maildir_storage->md_cached)
136 driver = maildir_cached_session_driver;
137 else
138 driver = maildir_session_driver;
139
140 session = mailsession_new(driver);
141 if (session == NULL) {
142 res = MAIL_ERROR_MEMORY;
143 goto err;
144 }
145
146 if (maildir_storage->md_cached) {
147 r = mailsession_parameters(session,
148 MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY,
149 maildir_storage->md_cache_directory);
150 if (r != MAIL_NO_ERROR) {
151 res = r;
152 goto free;
153 }
154
155 r = mailsession_parameters(session,
156 MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY,
157 maildir_storage->md_flags_directory);
158 if (r != MAIL_NO_ERROR) {
159 res = r;
160 goto free;
161 }
162 }
163
164 r = mailsession_connect_path(session, maildir_storage->md_pathname);
165 switch (r) {
166 case MAIL_NO_ERROR_NON_AUTHENTICATED:
167 case MAIL_NO_ERROR_AUTHENTICATED:
168 case MAIL_NO_ERROR:
169 break;
170 default:
171 res = r;
172 goto free;
173 }
174
175 storage->sto_session = session;
176
177 return MAIL_NO_ERROR;
178
179 free:
180 mailsession_free(session);
181 err:
182 return res;
183}
184
185static int
186maildir_mailstorage_get_folder_session(struct mailstorage * storage,
187 char * pathname, mailsession ** result)
188{
189 * result = storage->sto_session;
190
191 return MAIL_NO_ERROR;
192}
193
diff --git a/libetpan/src/driver/implementation/maildir/maildirstorage.h b/libetpan/src/driver/implementation/maildir/maildirstorage.h
new file mode 100644
index 0000000..0ad04b9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirstorage.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIRSTORAGE_H
37
38#define MAILDIRSTORAGE_H
39
40#include <libetpan/maildirdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 maildir_mailstorage_init is the constructor for a maildir storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the directory that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int maildir_mailstorage_init(struct mailstorage * storage,
62 char * md_pathname, int md_cached,
63 char * md_cache_directory, char * md_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.c b/libetpan/src/driver/implementation/mbox/mboxdriver.c
new file mode 100644
index 0000000..72afa6d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver.c
@@ -0,0 +1,515 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <sys/types.h>
41#include <dirent.h>
42#include <unistd.h>
43#include <sys/stat.h>
44#include <ctype.h>
45#include <stdlib.h>
46#include <sys/times.h>
47
48#include "mail.h"
49#include "maildriver_tools.h"
50#include "mailmbox.h"
51#include "mboxdriver_tools.h"
52#include "maildriver.h"
53#include "carray.h"
54#include "mboxdriver_message.h"
55#include "mailmessage.h"
56
57static int mboxdriver_initialize(mailsession * session);
58
59static void mboxdriver_uninitialize(mailsession * session);
60
61static int mboxdriver_parameters(mailsession * session,
62 int id, void * value);
63
64static int mboxdriver_connect_path(mailsession * session, char * path);
65
66static int mboxdriver_logout(mailsession * session);
67
68static int mboxdriver_expunge_folder(mailsession * session);
69
70static int mboxdriver_status_folder(mailsession * session, char * mb,
71 uint32_t * result_messages, uint32_t * result_recent,
72 uint32_t * result_unseen);
73
74static int mboxdriver_messages_number(mailsession * session, char * mb,
75 uint32_t * result);
76
77static int mboxdriver_append_message(mailsession * session,
78 char * message, size_t size);
79
80static int mboxdriver_append_message_flags(mailsession * session,
81 char * message, size_t size, struct mail_flags * flags);
82
83static int mboxdriver_get_messages_list(mailsession * session,
84 struct mailmessage_list ** result);
85
86static int
87mboxdriver_get_envelopes_list(mailsession * session,
88 struct mailmessage_list * env_list);
89
90static int mboxdriver_remove_message(mailsession * session, uint32_t num);
91
92static int mboxdriver_get_message(mailsession * session,
93 uint32_t num, mailmessage ** result);
94
95static int mboxdriver_get_message_by_uid(mailsession * session,
96 const char * uid,
97 mailmessage ** result);
98
99static mailsession_driver local_mbox_session_driver = {
100 .sess_name = "mbox",
101
102 .sess_initialize = mboxdriver_initialize,
103 .sess_uninitialize = mboxdriver_uninitialize,
104
105 .sess_parameters = mboxdriver_parameters,
106
107 .sess_connect_path = mboxdriver_connect_path,
108 .sess_connect_stream = NULL,
109 .sess_starttls = NULL,
110 .sess_login = NULL,
111 .sess_logout = mboxdriver_logout,
112 .sess_noop = NULL,
113
114 .sess_build_folder_name = NULL,
115 .sess_create_folder = NULL,
116 .sess_delete_folder = NULL,
117 .sess_rename_folder = NULL,
118 .sess_check_folder = NULL,
119 .sess_examine_folder = NULL,
120 .sess_select_folder = NULL,
121 .sess_expunge_folder = mboxdriver_expunge_folder,
122 .sess_status_folder = mboxdriver_status_folder,
123 .sess_messages_number = mboxdriver_messages_number,
124 .sess_recent_number = mboxdriver_messages_number,
125 .sess_unseen_number = mboxdriver_messages_number,
126 .sess_list_folders = NULL,
127 .sess_lsub_folders = NULL,
128 .sess_subscribe_folder = NULL,
129 .sess_unsubscribe_folder = NULL,
130
131 .sess_append_message = mboxdriver_append_message,
132 .sess_append_message_flags = mboxdriver_append_message_flags,
133 .sess_copy_message = NULL,
134 .sess_move_message = NULL,
135
136 .sess_get_messages_list = mboxdriver_get_messages_list,
137 .sess_get_envelopes_list = mboxdriver_get_envelopes_list,
138 .sess_remove_message = mboxdriver_remove_message,
139#if 0
140 .sess_search_messages = maildriver_generic_search_messages,
141#endif
142
143 .sess_get_message = mboxdriver_get_message,
144 .sess_get_message_by_uid = mboxdriver_get_message_by_uid,
145};
146
147mailsession_driver * mbox_session_driver = &local_mbox_session_driver;
148
149static inline struct mbox_session_state_data * get_data(mailsession * session)
150{
151 return session->sess_data;
152}
153
154static inline struct mailmbox_folder * get_mbox_session(mailsession * session)
155{
156 return get_data(session)->mbox_folder;
157}
158
159static int mboxdriver_initialize(mailsession * session)
160{
161 struct mbox_session_state_data * data;
162
163 data = malloc(sizeof(* data));
164 if (data == NULL)
165 goto err;
166
167 data->mbox_folder = NULL;
168
169 data->mbox_force_read_only = FALSE;
170 data->mbox_force_no_uid = TRUE;
171
172 session->sess_data = data;
173
174 return MAIL_NO_ERROR;
175
176 err:
177 return MAIL_ERROR_MEMORY;
178}
179
180static void free_state(struct mbox_session_state_data * mbox_data)
181{
182 if (mbox_data->mbox_folder != NULL) {
183 mailmbox_done(mbox_data->mbox_folder);
184 mbox_data->mbox_folder = NULL;
185 }
186}
187
188static void mboxdriver_uninitialize(mailsession * session)
189{
190 struct mbox_session_state_data * data;
191
192 data = get_data(session);
193
194 free_state(data);
195
196 free(data);
197}
198
199static int mboxdriver_parameters(mailsession * session,
200 int id, void * value)
201{
202 struct mbox_session_state_data * data;
203
204 data = get_data(session);
205
206 switch (id) {
207 case MBOXDRIVER_SET_READ_ONLY:
208 {
209 int * param;
210
211 param = value;
212
213 data->mbox_force_read_only = * param;
214 return MAIL_NO_ERROR;
215 }
216
217 case MBOXDRIVER_SET_NO_UID:
218 {
219 int * param;
220
221 param = value;
222
223 data->mbox_force_no_uid = * param;
224 return MAIL_NO_ERROR;
225 }
226 }
227
228 return MAIL_ERROR_INVAL;
229}
230
231
232static int mboxdriver_connect_path(mailsession * session, char * path)
233{
234 struct mbox_session_state_data * mbox_data;
235 struct mailmbox_folder * folder;
236 int r;
237
238 mbox_data = get_data(session);
239
240 if (mbox_data->mbox_folder != NULL)
241 return MAIL_ERROR_BAD_STATE;
242
243 r = mailmbox_init(path,
244 mbox_data->mbox_force_read_only,
245 mbox_data->mbox_force_no_uid,
246 0,
247 &folder);
248
249 if (r != MAILMBOX_NO_ERROR)
250 return mboxdriver_mbox_error_to_mail_error(r);
251
252 mbox_data->mbox_folder = folder;
253
254 return MAIL_NO_ERROR;
255}
256
257static int mboxdriver_logout(mailsession * session)
258{
259 struct mbox_session_state_data * mbox_data;
260
261 mbox_data = get_data(session);
262
263 if (mbox_data->mbox_folder == NULL)
264 return MAIL_ERROR_BAD_STATE;
265
266 free_state(mbox_data);
267
268 mbox_data->mbox_folder = NULL;
269
270 return MAIL_NO_ERROR;
271}
272
273static int mboxdriver_expunge_folder(mailsession * session)
274{
275 int r;
276 struct mbox_session_state_data * mbox_data;
277
278 mbox_data = get_data(session);
279
280 if (mbox_data->mbox_folder == NULL)
281 return MAIL_ERROR_BAD_STATE;
282
283 r = mailmbox_expunge(mbox_data->mbox_folder);
284 if (r != MAILMBOX_NO_ERROR)
285 return mboxdriver_mbox_error_to_mail_error(r);
286
287 return MAIL_NO_ERROR;
288}
289
290static int mboxdriver_status_folder(mailsession * session, char * mb,
291 uint32_t * result_messages, uint32_t * result_recent,
292 uint32_t * result_unseen)
293{
294 uint32_t count;
295 int r;
296
297 r = mboxdriver_messages_number(session, mb, &count);
298 if (r != MAIL_NO_ERROR)
299 return r;
300
301 * result_messages = count;
302 * result_recent = count;
303 * result_unseen = count;
304
305 return MAIL_NO_ERROR;
306}
307
308static int mboxdriver_messages_number(mailsession * session, char * mb,
309 uint32_t * result)
310{
311 struct mailmbox_folder * folder;
312 int r;
313
314 folder = get_mbox_session(session);
315 if (folder == NULL)
316 return MAIL_ERROR_STATUS;
317
318 r = mailmbox_validate_read_lock(folder);
319 if (r != MAIL_NO_ERROR)
320 return r;
321
322 mailmbox_read_unlock(folder);
323
324 * result = carray_count(folder->mb_tab) - folder->mb_deleted_count;
325
326 return MAILMBOX_NO_ERROR;
327}
328
329/* messages operations */
330
331static int mboxdriver_append_message(mailsession * session,
332 char * message, size_t size)
333{
334 int r;
335 struct mailmbox_folder * folder;
336
337 folder = get_mbox_session(session);
338 if (folder == NULL)
339 return MAIL_ERROR_APPEND;
340
341 r = mailmbox_append_message(folder, message, size);
342
343 switch (r) {
344 case MAILMBOX_ERROR_FILE:
345 return MAIL_ERROR_DISKSPACE;
346 default:
347 return mboxdriver_mbox_error_to_mail_error(r);
348 }
349}
350
351static int mboxdriver_append_message_flags(mailsession * session,
352 char * message, size_t size, struct mail_flags * flags)
353{
354 return mboxdriver_append_message(session, message, size);
355}
356
357static int mboxdriver_get_messages_list(mailsession * session,
358 struct mailmessage_list ** result)
359{
360 struct mailmbox_folder * folder;
361 int res;
362
363 folder = get_mbox_session(session);
364 if (folder == NULL) {
365 res = MAIL_ERROR_BAD_STATE;
366 goto err;
367 }
368
369 return mbox_get_messages_list(folder, session, mbox_message_driver, result);
370
371 err:
372 return res;
373}
374
375static int
376mboxdriver_get_envelopes_list(mailsession * session,
377 struct mailmessage_list * env_list)
378{
379 struct mailmbox_folder * folder;
380 unsigned int i;
381 int r;
382 int res;
383
384 folder = get_mbox_session(session);
385 if (folder == NULL) {
386 res = MAIL_ERROR_BAD_STATE;
387 goto err;
388 }
389
390 r = mailmbox_validate_read_lock(folder);
391 if (r != MAILMBOX_NO_ERROR) {
392 res = mboxdriver_mbox_error_to_mail_error(r);
393 goto err;
394 }
395
396 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
397 mailmessage * msg;
398 struct mailimf_fields * fields;
399 char * headers;
400 size_t headers_len;
401 size_t cur_token;
402
403 msg = carray_get(env_list->msg_tab, i);
404 if (msg == NULL)
405 continue;
406
407 if (msg->msg_fields != NULL)
408 continue;
409
410 r = mailmbox_fetch_msg_headers_no_lock(folder,
411 msg->msg_index, &headers, &headers_len);
412 if (r != MAILMBOX_NO_ERROR) {
413 res = mboxdriver_mbox_error_to_mail_error(r);
414 goto unlock;
415 }
416
417 cur_token = 0;
418 r = mailimf_envelope_fields_parse(headers, headers_len,
419 &cur_token, &fields);
420
421 if (r != MAILIMF_NO_ERROR)
422 continue;
423
424 msg->msg_fields = fields;
425 }
426
427 mailmbox_read_unlock(folder);
428
429 return MAIL_NO_ERROR;
430
431 unlock:
432 mailmbox_read_unlock(folder);
433 err:
434 return res;
435}
436
437
438static int mboxdriver_remove_message(mailsession * session, uint32_t num)
439{
440 int r;
441 struct mailmbox_folder * folder;
442
443 folder = get_mbox_session(session);
444 if (folder == NULL)
445 return MAIL_ERROR_DELETE;
446
447 r = mailmbox_delete_msg(folder, num);
448
449 return mboxdriver_mbox_error_to_mail_error(r);
450}
451
452static int mboxdriver_get_message(mailsession * session,
453 uint32_t num, mailmessage ** result)
454{
455 mailmessage * msg_info;
456 int r;
457
458 msg_info = mailmessage_new();
459 if (msg_info == NULL)
460 return MAIL_ERROR_MEMORY;
461
462 r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0);
463 if (r != MAIL_NO_ERROR) {
464 mailmessage_free(msg_info);
465 return r;
466 }
467
468 * result = msg_info;
469
470 return MAIL_NO_ERROR;
471}
472
473static int mboxdriver_get_message_by_uid(mailsession * session,
474 const char * uid,
475 mailmessage ** result)
476{
477 uint32_t num;
478 char * p;
479 chashdatum key;
480 chashdatum data;
481 struct mailmbox_msg_info * info;
482 struct mailmbox_folder * folder;
483 int r;
484
485 if (uid == NULL)
486 return MAIL_ERROR_INVAL;
487
488 num = strtoul(uid, &p, 10);
489 if (p == uid || * p != '-')
490 return MAIL_ERROR_INVAL;
491
492 folder = get_mbox_session(session);
493 if (folder == NULL)
494 return MAIL_ERROR_BAD_STATE;
495
496 key.data = &num;
497 key.len = sizeof(num);
498
499 r = chash_get(folder->mb_hash, &key, &data);
500 if (r == 0) {
501 char * body_len_p = p + 1;
502 size_t body_len;
503
504 info = data.data;
505 /* Check if the cached message has the same UID */
506 body_len = strtoul(body_len_p, &p, 10);
507 if (p == body_len_p || * p != '\0')
508 return MAIL_ERROR_INVAL;
509
510 if (body_len == info->msg_body_len)
511 return mboxdriver_get_message(session, num, result);
512 }
513
514 return MAIL_ERROR_MSG_NOT_FOUND;
515}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver.h b/libetpan/src/driver/implementation/mbox/mboxdriver.h
new file mode 100644
index 0000000..9b37aa4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_H
37
38#define MBOXDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mboxdriver_types.h>
45
46extern mailsession_driver * mbox_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c
new file mode 100644
index 0000000..eaa0e48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c
@@ -0,0 +1,1337 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_cached.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <ctype.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "mail_cache_db.h"
50#include "mboxdriver.h"
51#include "mboxdriver_tools.h"
52#include "maildriver_tools.h"
53#include "mailmbox.h"
54#include "maildriver.h"
55#include "carray.h"
56#include "generic_cache.h"
57#include "imfcache.h"
58#include "mboxdriver_cached_message.h"
59#include "libetpan-config.h"
60
61static int mboxdriver_cached_initialize(mailsession * session);
62
63static void mboxdriver_cached_uninitialize(mailsession * session);
64
65static int mboxdriver_cached_parameters(mailsession * session,
66 int id, void * value);
67
68static int mboxdriver_cached_connect_path(mailsession * session, char * path);
69
70static int mboxdriver_cached_logout(mailsession * session);
71
72static int mboxdriver_cached_check_folder(mailsession * session);
73
74static int mboxdriver_cached_expunge_folder(mailsession * session);
75
76static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
77 uint32_t * result_messages, uint32_t * result_recent,
78 uint32_t * result_unseen);
79static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
80 uint32_t * result);
81static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
82 uint32_t * result);
83static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
84 uint32_t * result);
85
86static int mboxdriver_cached_append_message(mailsession * session,
87 char * message, size_t size);
88
89static int mboxdriver_cached_append_message_flags(mailsession * session,
90 char * message, size_t size, struct mail_flags * flags);
91
92static int
93mboxdriver_cached_get_messages_list(mailsession * session,
94 struct mailmessage_list ** result);
95
96static int
97mboxdriver_cached_get_envelopes_list(mailsession * session,
98 struct mailmessage_list * env_list);
99
100static int mboxdriver_cached_remove_message(mailsession * session,
101 uint32_t num);
102
103static int mboxdriver_cached_get_message(mailsession * session,
104 uint32_t num, mailmessage ** result);
105
106static int mboxdriver_cached_get_message_by_uid(mailsession * session,
107 const char * uid,
108 mailmessage ** result);
109
110static mailsession_driver local_mbox_cached_session_driver = {
111 .sess_name = "mbox-cached",
112
113 .sess_initialize = mboxdriver_cached_initialize,
114 .sess_uninitialize = mboxdriver_cached_uninitialize,
115
116 .sess_parameters = mboxdriver_cached_parameters,
117
118 .sess_connect_path = mboxdriver_cached_connect_path,
119 .sess_connect_stream = NULL,
120 .sess_starttls = NULL,
121 .sess_login = NULL,
122 .sess_logout = mboxdriver_cached_logout,
123 .sess_noop = NULL,
124
125 .sess_build_folder_name = NULL,
126 .sess_create_folder = NULL,
127 .sess_delete_folder = NULL,
128 .sess_rename_folder = NULL,
129 .sess_check_folder = mboxdriver_cached_check_folder,
130 .sess_examine_folder = NULL,
131 .sess_select_folder = NULL,
132 .sess_expunge_folder = mboxdriver_cached_expunge_folder,
133 .sess_status_folder = mboxdriver_cached_status_folder,
134 .sess_messages_number = mboxdriver_cached_messages_number,
135 .sess_recent_number = mboxdriver_cached_recent_number,
136 .sess_unseen_number = mboxdriver_cached_unseen_number,
137 .sess_list_folders = NULL,
138 .sess_lsub_folders = NULL,
139 .sess_subscribe_folder = NULL,
140 .sess_unsubscribe_folder = NULL,
141
142 .sess_append_message = mboxdriver_cached_append_message,
143 .sess_append_message_flags = mboxdriver_cached_append_message_flags,
144
145 .sess_copy_message = NULL,
146 .sess_move_message = NULL,
147
148 .sess_get_messages_list = mboxdriver_cached_get_messages_list,
149 .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list,
150 .sess_remove_message = mboxdriver_cached_remove_message,
151#if 0
152 .sess_search_messages = maildriver_generic_search_messages,
153#endif
154
155 .sess_get_message = mboxdriver_cached_get_message,
156 .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid,
157};
158
159mailsession_driver * mbox_cached_session_driver =
160&local_mbox_cached_session_driver;
161
162
163#define ENV_NAME "env.db"
164#define FLAGS_NAME "flags.db"
165
166
167
168static int mbox_error_to_mail_error(int error)
169{
170 switch (error) {
171 case MAILMBOX_NO_ERROR:
172 return MAIL_NO_ERROR;
173
174 case MAILMBOX_ERROR_PARSE:
175 return MAIL_ERROR_PARSE;
176
177 case MAILMBOX_ERROR_INVAL:
178 return MAIL_ERROR_INVAL;
179
180 case MAILMBOX_ERROR_FILE_NOT_FOUND:
181 return MAIL_ERROR_PARSE;
182
183 case MAILMBOX_ERROR_MEMORY:
184 return MAIL_ERROR_MEMORY;
185
186 case MAILMBOX_ERROR_TEMPORARY_FILE:
187 return MAIL_ERROR_PARSE;
188
189 case MAILMBOX_ERROR_FILE:
190 return MAIL_ERROR_FILE;
191
192 case MAILMBOX_ERROR_MSG_NOT_FOUND:
193 return MAIL_ERROR_MSG_NOT_FOUND;
194
195 case MAILMBOX_ERROR_READONLY:
196 return MAIL_ERROR_READONLY;
197
198 default:
199 return MAIL_ERROR_INVAL;
200 }
201}
202
203
204
205
206static inline struct mbox_cached_session_state_data *
207get_cached_data(mailsession * session)
208{
209 return session->sess_data;
210}
211
212static inline mailsession * get_ancestor(mailsession * session)
213{
214 return get_cached_data(session)->mbox_ancestor;
215}
216
217static inline struct mbox_session_state_data *
218get_ancestor_data(mailsession * session)
219{
220 return get_ancestor(session)->sess_data;
221}
222
223static inline struct mailmbox_folder *
224get_mbox_session(mailsession * session)
225{
226 return get_ancestor_data(session)->mbox_folder;
227}
228
229static int mboxdriver_cached_initialize(mailsession * session)
230{
231 struct mbox_cached_session_state_data * cached_data;
232 struct mbox_session_state_data * mbox_data;
233
234 cached_data = malloc(sizeof(* cached_data));
235 if (cached_data == NULL)
236 goto err;
237
238 cached_data->mbox_flags_store = mail_flags_store_new();
239 if (cached_data->mbox_flags_store == NULL)
240 goto free;
241
242 cached_data->mbox_ancestor = mailsession_new(mbox_session_driver);
243 if (cached_data->mbox_ancestor == NULL)
244 goto free_store;
245
246 cached_data->mbox_quoted_mb = NULL;
247 /*
248 UID must be enabled to take advantage of the cache
249 */
250 mbox_data = cached_data->mbox_ancestor->sess_data;
251 mbox_data->mbox_force_no_uid = FALSE;
252
253 session->sess_data = cached_data;
254
255 return MAIL_NO_ERROR;
256
257 free_store:
258 mail_flags_store_free(cached_data->mbox_flags_store);
259 free:
260 free(cached_data);
261 err:
262 return MAIL_ERROR_MEMORY;
263}
264
265static void free_state(struct mbox_cached_session_state_data * mbox_data)
266{
267 if (mbox_data->mbox_quoted_mb) {
268 free(mbox_data->mbox_quoted_mb);
269 mbox_data->mbox_quoted_mb = NULL;
270 }
271}
272
273static int mbox_flags_store_process(char * flags_directory, char * quoted_mb,
274 struct mail_flags_store * flags_store)
275{
276 char filename_flags[PATH_MAX];
277 struct mail_cache_db * cache_db_flags;
278 MMAPString * mmapstr;
279 unsigned int i;
280 int r;
281 int res;
282
283 if (carray_count(flags_store->fls_tab) == 0)
284 return MAIL_NO_ERROR;
285
286 if (quoted_mb == NULL)
287 return MAIL_NO_ERROR;
288
289 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
290 flags_directory, MAIL_DIR_SEPARATOR, quoted_mb,
291 MAIL_DIR_SEPARATOR, FLAGS_NAME);
292
293 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
294 if (r < 0) {
295 res = MAIL_ERROR_FILE;
296 goto err;
297 }
298
299 mmapstr = mmap_string_new("");
300 if (mmapstr == NULL) {
301 res = MAIL_ERROR_MEMORY;
302 goto close_db_flags;
303 }
304
305 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
306 mailmessage * msg;
307
308 msg = carray_get(flags_store->fls_tab, i);
309
310 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
311 msg->msg_uid, msg->msg_flags);
312 if (r != MAIL_NO_ERROR) {
313 /* ignore errors */
314 }
315 }
316
317 mmap_string_free(mmapstr);
318 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
319
320 mail_flags_store_clear(flags_store);
321
322 return MAIL_NO_ERROR;
323
324 close_db_flags:
325 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
326 err:
327 return res;
328}
329
330static void mboxdriver_cached_uninitialize(mailsession * session)
331{
332 struct mbox_cached_session_state_data * data;
333
334 data = get_cached_data(session);
335
336 mbox_flags_store_process(data->mbox_flags_directory,
337 data->mbox_quoted_mb,
338 data->mbox_flags_store);
339
340 mail_flags_store_free(data->mbox_flags_store);
341
342 free_state(data);
343 mailsession_free(data->mbox_ancestor);
344 free(data);
345
346 session->sess_data = NULL;
347}
348
349static int mboxdriver_cached_parameters(mailsession * session,
350 int id, void * value)
351{
352 struct mbox_cached_session_state_data * data;
353 int r;
354
355 data = get_cached_data(session);
356
357 switch (id) {
358 case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY:
359 strncpy(data->mbox_cache_directory, value, PATH_MAX);
360 data->mbox_cache_directory[PATH_MAX - 1] = '\0';
361
362 r = generic_cache_create_dir(data->mbox_cache_directory);
363 if (r != MAIL_NO_ERROR)
364 return r;
365
366 return MAIL_NO_ERROR;
367
368 case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY:
369 strncpy(data->mbox_flags_directory, value, PATH_MAX);
370 data->mbox_flags_directory[PATH_MAX - 1] = '\0';
371
372 r = generic_cache_create_dir(data->mbox_flags_directory);
373 if (r != MAIL_NO_ERROR)
374 return r;
375
376 return MAIL_NO_ERROR;
377
378 case MBOXDRIVER_SET_NO_UID:
379 return MAIL_ERROR_INVAL;
380
381 default:
382 return mailsession_parameters(data->mbox_ancestor, id, value);
383 }
384}
385
386
387static int get_cache_directory(mailsession * session,
388 char * path, char ** result)
389{
390 char * quoted_mb;
391 char dirname[PATH_MAX];
392 int res;
393 int r;
394 struct mbox_cached_session_state_data * cached_data;
395
396 cached_data = get_cached_data(session);
397
398 quoted_mb = maildriver_quote_mailbox(path);
399 if (quoted_mb == NULL) {
400 res = MAIL_ERROR_MEMORY;
401 goto err;
402 }
403
404 snprintf(dirname, PATH_MAX, "%s%c%s",
405 cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb);
406
407 r = generic_cache_create_dir(dirname);
408 if (r != MAIL_NO_ERROR) {
409 res = r;
410 goto free;
411 }
412
413 snprintf(dirname, PATH_MAX, "%s%c%s",
414 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb);
415
416 r = generic_cache_create_dir(dirname);
417 if (r != MAIL_NO_ERROR) {
418 res = r;
419 goto free;
420 }
421
422 * result = quoted_mb;
423
424 return MAIL_NO_ERROR;
425
426 free:
427 free(quoted_mb);
428 err:
429 return res;
430}
431
432
433
434
435#define FILENAME_MAX_UID "max-uid"
436
437/* write max uid current value */
438
439static int write_max_uid_value(mailsession * session)
440{
441 int r;
442 char filename[PATH_MAX];
443 FILE * f;
444 int res;
445
446#if 0
447 struct mbox_session_state_data * mbox_data;
448#endif
449 struct mbox_cached_session_state_data * cached_data;
450 int fd;
451
452 MMAPString * mmapstr;
453 size_t cur_token;
454 struct mailmbox_folder * folder;
455
456 /* expunge the mailbox */
457
458#if 0
459 mbox_data = get_ancestor(session)->data;
460#endif
461 folder = get_mbox_session(session);
462
463 r = mailmbox_validate_write_lock(folder);
464 if (r != MAILMBOX_NO_ERROR) {
465 res = mbox_error_to_mail_error(r);
466 goto err;
467 }
468
469 r = mailmbox_expunge_no_lock(folder);
470 if (r != MAILMBOX_NO_ERROR) {
471 res = r;
472 goto unlock;
473 }
474
475 cached_data = get_cached_data(session);
476
477 snprintf(filename, PATH_MAX, "%s%c%s%c%s",
478 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
479 cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
480
481 fd = creat(filename, S_IRUSR | S_IWUSR);
482 if (fd < 0) {
483 res = MAIL_ERROR_FILE;
484 goto err;
485 }
486
487 f = fdopen(fd, "w");
488 if (f == NULL) {
489 close(fd);
490 res = MAIL_ERROR_FILE;
491 goto unlock;
492 }
493
494 mmapstr = mmap_string_new("");
495 if (mmapstr == NULL) {
496 res = MAIL_ERROR_MEMORY;
497 goto close;
498 }
499
500 r = mail_serialize_clear(mmapstr, &cur_token);
501 if (r != MAIL_NO_ERROR) {
502 res = r;
503 goto free_mmapstr;
504 }
505
506 r = mailimf_cache_int_write(mmapstr, &cur_token,
507 folder->mb_written_uid);
508 if (r != MAIL_NO_ERROR) {
509 res = r;
510 goto free_mmapstr;
511 }
512
513 fwrite(mmapstr->str, 1, mmapstr->len, f);
514
515 mmap_string_free(mmapstr);
516 fclose(f);
517 mailmbox_write_unlock(folder);
518
519 return MAIL_NO_ERROR;
520
521 free_mmapstr:
522 mmap_string_free(mmapstr);
523 close:
524 fclose(f);
525 unlock:
526 mailmbox_read_unlock(folder);
527 err:
528 return res;
529}
530
531static int read_max_uid_value(mailsession * session, uint32_t * result)
532{
533 int r;
534 char filename[PATH_MAX];
535 FILE * f;
536 uint32_t written_uid;
537 int res;
538
539 struct mbox_cached_session_state_data * cached_data;
540
541 MMAPString * mmapstr;
542 size_t cur_token;
543 char buf[sizeof(uint32_t)];
544 size_t read_size;
545
546 cached_data = get_cached_data(session);
547
548 snprintf(filename, PATH_MAX, "%s%c%s%c%s",
549 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
550 cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID);
551
552 f = fopen(filename, "r");
553 if (f == NULL) {
554 res = MAIL_ERROR_FILE;
555 goto err;
556 }
557
558 read_size = fread(buf, 1, sizeof(uint32_t), f);
559
560 mmapstr = mmap_string_new_len(buf, read_size);
561 if (mmapstr == NULL) {
562 res = MAIL_ERROR_MEMORY;
563 goto close;
564 }
565
566 cur_token = 0;
567
568 r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
569 if (r != MAIL_NO_ERROR) {
570 fclose(f);
571 res = r;
572 goto free_mmapstr;
573 }
574
575 mmap_string_free(mmapstr);
576 fclose(f);
577
578 * result = written_uid;
579
580 return MAIL_NO_ERROR;
581
582 free_mmapstr:
583 mmap_string_free(mmapstr);
584 close:
585 fclose(f);
586 err:
587 return res;
588}
589
590static int mboxdriver_cached_connect_path(mailsession * session, char * path)
591{
592 int r;
593 int res;
594 char * quoted_mb;
595 struct mbox_cached_session_state_data * cached_data;
596 struct mbox_session_state_data * ancestor_data;
597 struct mailmbox_folder * folder;
598 uint32_t written_uid;
599
600 folder = get_mbox_session(session);
601 if (folder != NULL) {
602 res = MAIL_ERROR_BAD_STATE;
603 goto err;
604 }
605
606 r = get_cache_directory(session, path, &quoted_mb);
607 if (r != MAIL_NO_ERROR) {
608 res = r;
609 goto err;
610 }
611
612 cached_data = get_cached_data(session);
613 free_state(cached_data);
614
615 cached_data->mbox_quoted_mb = quoted_mb;
616
617 written_uid = 0;
618 r = read_max_uid_value(session, &written_uid);
619 /* ignore errors */
620
621 ancestor_data = get_ancestor_data(session);
622
623 r = mailmbox_init(path,
624 ancestor_data->mbox_force_read_only,
625 ancestor_data->mbox_force_no_uid,
626 written_uid,
627 &folder);
628
629 if (r != MAILMBOX_NO_ERROR) {
630 cached_data->mbox_quoted_mb = NULL;
631
632 res = mboxdriver_mbox_error_to_mail_error(r);
633 goto free;
634 }
635
636 ancestor_data->mbox_folder = folder;
637
638 return MAIL_NO_ERROR;
639
640 free:
641 free(quoted_mb);
642 err:
643 return res;
644}
645
646
647static int mboxdriver_cached_logout(mailsession * session)
648{
649 struct mbox_cached_session_state_data * cached_data;
650 int r;
651
652 r = write_max_uid_value(session);
653
654 cached_data = get_cached_data(session);
655
656 mbox_flags_store_process(cached_data->mbox_flags_directory,
657 cached_data->mbox_quoted_mb,
658 cached_data->mbox_flags_store);
659
660 r = mailsession_logout(get_ancestor(session));
661 if (r != MAIL_NO_ERROR)
662 return r;
663
664 free_state(cached_data);
665
666 return MAIL_NO_ERROR;
667}
668
669static int mboxdriver_cached_check_folder(mailsession * session)
670{
671 struct mbox_cached_session_state_data * cached_data;
672
673 cached_data = get_cached_data(session);
674
675 mbox_flags_store_process(cached_data->mbox_flags_directory,
676 cached_data->mbox_quoted_mb,
677 cached_data->mbox_flags_store);
678
679 return MAIL_NO_ERROR;
680}
681
682static int mboxdriver_cached_expunge_folder(mailsession * session)
683{
684 struct mailmbox_folder * folder;
685 int res;
686 char filename_flags[PATH_MAX];
687 struct mail_cache_db * cache_db_flags;
688 MMAPString * mmapstr;
689 struct mbox_cached_session_state_data * data;
690 int r;
691 unsigned int i;
692
693 folder = get_mbox_session(session);
694 if (folder == NULL) {
695 res = MAIL_ERROR_BAD_STATE;
696 goto err;
697 }
698
699 data = get_cached_data(session);
700 if (data->mbox_quoted_mb == NULL) {
701 res = MAIL_ERROR_BAD_STATE;
702 goto err;
703 }
704
705 mbox_flags_store_process(data->mbox_flags_directory,
706 data->mbox_quoted_mb,
707 data->mbox_flags_store);
708
709 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
710 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
711 MAIL_DIR_SEPARATOR, FLAGS_NAME);
712
713 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
714 if (r < 0) {
715 res = MAIL_ERROR_FILE;
716 goto err;
717 }
718
719 mmapstr = mmap_string_new("");
720 if (mmapstr == NULL) {
721 res = MAIL_ERROR_MEMORY;
722 goto close_db_flags;
723 }
724
725 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
726 struct mailmbox_msg_info * msg_info;
727 struct mail_flags * flags;
728
729 msg_info = carray_get(folder->mb_tab, i);
730 if (msg_info == NULL)
731 continue;
732
733 if (msg_info->msg_deleted)
734 continue;
735
736 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
737 session, msg_info->msg_uid, &flags);
738 if (r != MAIL_NO_ERROR)
739 continue;
740
741 if (flags->fl_flags & MAIL_FLAG_DELETED) {
742 r = mailmbox_delete_msg(folder, msg_info->msg_uid);
743 }
744
745 mail_flags_free(flags);
746 }
747
748 mmap_string_free(mmapstr);
749 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
750
751 r = mailmbox_expunge(folder);
752
753 return MAIL_NO_ERROR;
754
755 close_db_flags:
756 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
757 err:
758 return res;
759}
760
761static int mboxdriver_cached_status_folder(mailsession * session, char * mb,
762 uint32_t * result_messages, uint32_t * result_recent,
763 uint32_t * result_unseen)
764{
765 struct mailmbox_folder * folder;
766 int res;
767 char filename_flags[PATH_MAX];
768 struct mail_cache_db * cache_db_flags;
769 MMAPString * mmapstr;
770 struct mbox_cached_session_state_data * data;
771 int r;
772 unsigned int i;
773 uint32_t recent;
774 uint32_t unseen;
775 uint32_t num;
776
777 num = 0;
778 recent = 0;
779 unseen = 0;
780
781 folder = get_mbox_session(session);
782 if (folder == NULL) {
783 res = MAIL_ERROR_BAD_STATE;
784 goto err;
785 }
786
787 data = get_cached_data(session);
788 if (data->mbox_quoted_mb == NULL) {
789 res = MAIL_ERROR_BAD_STATE;
790 goto err;
791 }
792
793 r = mailmbox_validate_read_lock(folder);
794 if (r != MAIL_NO_ERROR) {
795 res = MAIL_ERROR_BAD_STATE;
796 goto err;
797 }
798
799 mailmbox_read_unlock(folder);
800
801 mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb,
802 data->mbox_flags_store);
803
804 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
805 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
806 MAIL_DIR_SEPARATOR, FLAGS_NAME);
807
808 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
809 if (r < 0) {
810 res = MAIL_ERROR_FILE;
811 goto err;
812 }
813
814 mmapstr = mmap_string_new("");
815 if (mmapstr == NULL) {
816 res = MAIL_ERROR_MEMORY;
817 goto close_db_flags;
818 }
819
820 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
821 struct mailmbox_msg_info * msg_info;
822 struct mail_flags * flags;
823
824 msg_info = carray_get(folder->mb_tab, i);
825 if (msg_info == NULL)
826 continue;
827
828 if (msg_info->msg_deleted)
829 continue;
830
831 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
832 session, msg_info->msg_uid, &flags);
833 if (r != MAIL_NO_ERROR) {
834 recent ++;
835 unseen ++;
836 num ++;
837 continue;
838 }
839
840 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
841 recent ++;
842 }
843 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
844 unseen ++;
845 }
846
847 num ++;
848
849 mail_flags_free(flags);
850 }
851
852 mmap_string_free(mmapstr);
853 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
854
855 * result_messages = num;
856 * result_recent = recent;
857 * result_unseen = unseen;
858
859 return MAIL_NO_ERROR;
860
861 close_db_flags:
862 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
863 err:
864 return res;
865}
866
867static int mboxdriver_cached_messages_number(mailsession * session, char * mb,
868 uint32_t * result)
869{
870 return mailsession_messages_number(get_ancestor(session), mb, result);
871}
872
873
874static int mboxdriver_cached_recent_number(mailsession * session, char * mb,
875 uint32_t * result)
876{
877 uint32_t messages;
878 uint32_t recent;
879 uint32_t unseen;
880 int r;
881
882 r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
883 if (r != MAIL_NO_ERROR)
884 return r;
885
886 * result = recent;
887
888 return MAIL_NO_ERROR;
889}
890
891static int mboxdriver_cached_unseen_number(mailsession * session, char * mb,
892 uint32_t * result)
893{
894 uint32_t messages;
895 uint32_t recent;
896 uint32_t unseen;
897 int r;
898
899 r = mboxdriver_cached_status_folder(session, mb,
900 &messages, &recent, &unseen);
901 if (r != MAIL_NO_ERROR)
902 return r;
903
904 * result = unseen;
905
906 return MAIL_NO_ERROR;
907}
908
909/* messages operations */
910
911static int mboxdriver_cached_append_message(mailsession * session,
912 char * message, size_t size)
913{
914 return mboxdriver_cached_append_message_flags(session,
915 message, size, NULL);
916}
917
918static int mboxdriver_cached_append_message_flags(mailsession * session,
919 char * message, size_t size, struct mail_flags * flags)
920{
921 int r;
922 struct mailmbox_folder * folder;
923 struct mbox_cached_session_state_data * data;
924 unsigned int uid;
925 struct mailmbox_msg_info * msg_info;
926 chashdatum key;
927 chashdatum value;
928 struct mail_cache_db * cache_db_flags;
929 char filename_flags[PATH_MAX];
930 MMAPString * mmapstr;
931 char keyname[PATH_MAX];
932
933 folder = get_mbox_session(session);
934 if (folder == NULL)
935 return MAIL_ERROR_APPEND;
936
937 r = mailmbox_append_message_uid(folder, message, size, &uid);
938
939 switch (r) {
940 case MAILMBOX_ERROR_FILE:
941 return MAIL_ERROR_DISKSPACE;
942 case MAILMBOX_NO_ERROR:
943 break;
944 default:
945 return mboxdriver_mbox_error_to_mail_error(r);
946 }
947
948 /* could store in flags store instead */
949
950 if (flags == NULL)
951 goto exit;
952
953 key.data = &uid;
954 key.len = sizeof(uid);
955 r = chash_get(folder->mb_hash, &key, &value);
956 if (r < 0)
957 goto exit;
958
959 msg_info = value.data;
960
961 data = get_cached_data(session);
962
963 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
964 data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb,
965 MAIL_DIR_SEPARATOR, FLAGS_NAME);
966
967 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
968 if (r < 0)
969 goto exit;
970
971 mmapstr = mmap_string_new("");
972 if (mmapstr == NULL)
973 goto close_db_flags;
974
975 snprintf(keyname, PATH_MAX, "%u-%lu", uid,
976 (unsigned long) msg_info->msg_body_len);
977
978 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
979
980 mmap_string_free(mmapstr);
981 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
982
983 if (r != MAIL_NO_ERROR)
984 goto exit;
985
986 return MAIL_NO_ERROR;
987
988 close_db_flags:
989 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
990 exit:
991 return MAIL_NO_ERROR;
992}
993
994static int
995mboxdriver_cached_get_messages_list(mailsession * session,
996 struct mailmessage_list ** result)
997{
998 struct mailmbox_folder * folder;
999 int res;
1000
1001 folder = get_mbox_session(session);
1002 if (folder == NULL) {
1003 res = MAIL_ERROR_BAD_STATE;
1004 goto err;
1005 }
1006
1007 return mbox_get_uid_messages_list(folder,
1008 session, mbox_cached_message_driver, result);
1009
1010 err:
1011 return res;
1012}
1013
1014static int
1015get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1016 mailsession * session, uint32_t num,
1017 struct mailimf_fields ** result)
1018{
1019 int r;
1020 char keyname[PATH_MAX];
1021 struct mailimf_fields * fields;
1022 int res;
1023 struct mailmbox_msg_info * info;
1024 struct mailmbox_folder * folder;
1025 chashdatum key;
1026 chashdatum data;
1027
1028 folder = get_mbox_session(session);
1029 if (folder == NULL) {
1030 res = MAIL_ERROR_BAD_STATE;
1031 goto err;
1032 }
1033
1034 key.data = &num;
1035 key.len = sizeof(num);
1036
1037 r = chash_get(folder->mb_hash, &key, &data);
1038 if (r < 0) {
1039 res = MAIL_ERROR_MSG_NOT_FOUND;
1040 goto err;
1041 }
1042
1043 info = data.data;
1044
1045 snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
1046 (unsigned long) info->msg_body_len);
1047
1048 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
1049 if (r != MAIL_NO_ERROR) {
1050 res = r;
1051 goto err;
1052 }
1053
1054 * result = fields;
1055
1056 return MAIL_NO_ERROR;
1057
1058 err:
1059 return res;
1060}
1061
1062static int
1063write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1064 mailsession * session, uint32_t num,
1065 struct mailimf_fields * fields)
1066{
1067 int r;
1068 char keyname[PATH_MAX];
1069 int res;
1070 struct mailmbox_msg_info * info;
1071 struct mailmbox_folder * folder;
1072 chashdatum key;
1073 chashdatum data;
1074
1075 folder = get_mbox_session(session);
1076 if (folder == NULL) {
1077 res = MAIL_ERROR_BAD_STATE;
1078 goto err;
1079 }
1080
1081 key.data = &num;
1082 key.len = sizeof(num);
1083
1084 r = chash_get(folder->mb_hash, &key, &data);
1085 if (r < 0) {
1086 res = MAIL_ERROR_MSG_NOT_FOUND;
1087 goto err;
1088 }
1089
1090 info = data.data;
1091
1092 snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num,
1093 (unsigned long) info->msg_body_len);
1094
1095 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
1096 if (r != MAIL_NO_ERROR) {
1097 res = r;
1098 goto err;
1099 }
1100
1101 return MAIL_NO_ERROR;
1102
1103 err:
1104 return res;
1105}
1106
1107static int
1108mboxdriver_cached_get_envelopes_list(mailsession * session,
1109 struct mailmessage_list * env_list)
1110{
1111 int r;
1112 unsigned int i;
1113 struct mbox_cached_session_state_data * cached_data;
1114 char filename_env[PATH_MAX];
1115 char filename_flags[PATH_MAX];
1116 struct mail_cache_db * cache_db_env;
1117 struct mail_cache_db * cache_db_flags;
1118 MMAPString * mmapstr;
1119 int res;
1120 struct mailmbox_folder * folder;
1121
1122 folder = get_mbox_session(session);
1123 if (folder == NULL) {
1124 res = MAIL_ERROR_BAD_STATE;
1125 goto err;
1126 }
1127
1128 cached_data = get_cached_data(session);
1129 if (cached_data->mbox_quoted_mb == NULL) {
1130 res = MAIL_ERROR_BAD_STATE;
1131 goto err;
1132 }
1133
1134 mbox_flags_store_process(cached_data->mbox_flags_directory,
1135 cached_data->mbox_quoted_mb,
1136 cached_data->mbox_flags_store);
1137
1138 mmapstr = mmap_string_new("");
1139 if (mmapstr == NULL) {
1140 res = MAIL_ERROR_MEMORY;
1141 goto err;
1142 }
1143
1144 snprintf(filename_env, PATH_MAX, "%s%c%s%c%s",
1145 cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR,
1146 cached_data->mbox_quoted_mb,
1147 MAIL_DIR_SEPARATOR, ENV_NAME);
1148
1149 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1150 if (r < 0) {
1151 res = MAIL_ERROR_MEMORY;
1152 goto free_mmapstr;
1153 }
1154
1155 snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s",
1156 cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR,
1157 cached_data->mbox_quoted_mb,
1158 MAIL_DIR_SEPARATOR, FLAGS_NAME);
1159
1160 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1161 if (r < 0) {
1162 res = MAIL_ERROR_FILE;
1163 goto close_db_env;
1164 }
1165
1166 /* fill with cached */
1167
1168 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1169 mailmessage * msg;
1170 struct mailimf_fields * fields;
1171 struct mail_flags * flags;
1172
1173 msg = carray_get(env_list->msg_tab, i);
1174
1175 if (msg->msg_fields == NULL) {
1176 r = get_cached_envelope(cache_db_env, mmapstr, session,
1177 msg->msg_index, &fields);
1178 if (r == MAIL_NO_ERROR) {
1179 msg->msg_cached = TRUE;
1180 msg->msg_fields = fields;
1181 }
1182 }
1183
1184 if (msg->msg_flags == NULL) {
1185 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
1186 session, msg->msg_index,
1187 &flags);
1188 if (r == MAIL_NO_ERROR) {
1189 msg->msg_flags = flags;
1190 }
1191 }
1192 }
1193
1194 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1195 mail_cache_db_close_unlock(filename_env, cache_db_env);
1196
1197 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1198
1199 if (r != MAIL_NO_ERROR) {
1200 res = r;
1201 goto free_mmapstr;
1202 }
1203
1204 /* add flags */
1205
1206 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1207 mailmessage * msg;
1208
1209 msg = carray_get(env_list->msg_tab, i);
1210
1211 if (msg->msg_flags == NULL)
1212 msg->msg_flags = mail_flags_new_empty();
1213 }
1214
1215 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1216 if (r < 0) {
1217 res = MAIL_ERROR_MEMORY;
1218 goto free_mmapstr;
1219 }
1220
1221 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1222 if (r < 0) {
1223 res = MAIL_ERROR_FILE;
1224 goto close_db_env;
1225 }
1226
1227 /* must write cache */
1228
1229 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1230 mailmessage * msg;
1231
1232 msg = carray_get(env_list->msg_tab, i);
1233
1234 if (msg->msg_fields != NULL) {
1235 if (!msg->msg_cached) {
1236 /* msg->msg_index is the numerical UID of the message */
1237 r = write_cached_envelope(cache_db_env, mmapstr,
1238 session, msg->msg_index, msg->msg_fields);
1239 }
1240 }
1241
1242 if (msg->msg_flags != NULL) {
1243 r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr,
1244 msg->msg_uid, msg->msg_flags);
1245 }
1246 }
1247
1248 /* flush cache */
1249
1250 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
1251
1252 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1253 mail_cache_db_close_unlock(filename_env, cache_db_env);
1254
1255 mmap_string_free(mmapstr);
1256
1257 return MAIL_NO_ERROR;
1258
1259 close_db_env:
1260 mail_cache_db_close_unlock(filename_env, cache_db_env);
1261 free_mmapstr:
1262 mmap_string_free(mmapstr);
1263 err:
1264 return res;
1265}
1266
1267
1268static int
1269mboxdriver_cached_remove_message(mailsession * session, uint32_t num)
1270{
1271 return mailsession_remove_message(get_ancestor(session), num);
1272}
1273
1274static int mboxdriver_cached_get_message(mailsession * session,
1275 uint32_t num, mailmessage ** result)
1276{
1277 mailmessage * msg_info;
1278 int r;
1279
1280 msg_info = mailmessage_new();
1281 if (msg_info == NULL)
1282 return MAIL_ERROR_MEMORY;
1283
1284 r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0);
1285 if (r != MAIL_NO_ERROR) {
1286 mailmessage_free(msg_info);
1287 return r;
1288 }
1289
1290 * result = msg_info;
1291
1292 return MAIL_NO_ERROR;
1293}
1294
1295static int mboxdriver_cached_get_message_by_uid(mailsession * session,
1296 const char * uid,
1297 mailmessage ** result)
1298{
1299 uint32_t num;
1300 char * p;
1301 chashdatum key;
1302 chashdatum data;
1303 struct mailmbox_msg_info * info;
1304 struct mailmbox_folder * folder;
1305 int r;
1306
1307 if (uid == NULL)
1308 return MAIL_ERROR_INVAL;
1309
1310 num = strtoul(uid, &p, 10);
1311 if (p == uid || * p != '-')
1312 return MAIL_ERROR_INVAL;
1313
1314 folder = get_mbox_session(session);
1315 if (folder == NULL)
1316 return MAIL_ERROR_BAD_STATE;
1317
1318 key.data = &num;
1319 key.len = sizeof(num);
1320
1321 r = chash_get(folder->mb_hash, &key, &data);
1322 if (r == 0) {
1323 char * body_len_p = p + 1;
1324 size_t body_len;
1325
1326 info = data.data;
1327 /* Check if the cached message has the same UID */
1328 body_len = strtoul(body_len_p, &p, 10);
1329 if (p == body_len_p || * p != '\0')
1330 return MAIL_ERROR_INVAL;
1331
1332 if (body_len == info->msg_body_len)
1333 return mboxdriver_cached_get_message(session, num, result);
1334 }
1335
1336 return MAIL_ERROR_MSG_NOT_FOUND;
1337}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h
new file mode 100644
index 0000000..25c4027
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_H
37
38#define MBOXDRIVER_CACHED_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mboxdriver_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48extern mailsession_driver * mbox_cached_session_driver;
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
new file mode 100644
index 0000000..9f77d32
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
@@ -0,0 +1,361 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_cached_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver_cached.h"
41#include "mboxdriver.h"
42#include "mailmbox.h"
43#include "mail_cache_db.h"
44#include "generic_cache.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mbox_prefetch(mailmessage * msg_info);
55
56static void mbox_prefetch_free(struct generic_message_t * msg);
57
58static int mbox_initialize(mailmessage * msg_info);
59
60static void mbox_uninitialize(mailmessage * msg_info);
61
62static void mbox_flush(mailmessage * msg_info);
63
64static void mbox_check(mailmessage * msg_info);
65
66static int mbox_fetch_size(mailmessage * msg_info,
67 size_t * result);
68
69static int mbox_get_flags(mailmessage * msg_info,
70 struct mail_flags ** result);
71
72static int mbox_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mbox_cached_message_driver = {
77 .msg_name = "mbox-cached",
78
79 .msg_initialize = mbox_initialize,
80 .msg_uninitialize = mbox_uninitialize,
81
82 .msg_flush = mbox_flush,
83 .msg_check = mbox_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mbox_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mbox_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mbox_get_flags,
99};
100
101mailmessage_driver * mbox_cached_message_driver =
102&local_mbox_cached_message_driver;
103
104static inline struct mbox_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mbox_ancestor;
113}
114
115static inline struct mbox_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmbox_folder *
122get_mbox_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mbox_folder;
125}
126
127static int mbox_prefetch(mailmessage * msg_info)
128{
129 struct generic_message_t * msg;
130 int r;
131 char * msg_content;
132 size_t msg_length;
133
134 r = mboxdriver_fetch_msg(get_ancestor_session(msg_info),
135 msg_info->msg_index,
136 &msg_content, &msg_length);
137 if (r != MAIL_NO_ERROR)
138 return r;
139
140 msg = msg_info->msg_data;
141
142 msg->msg_message = msg_content;
143 msg->msg_length = msg_length;
144
145 return MAIL_NO_ERROR;
146}
147
148static void mbox_prefetch_free(struct generic_message_t * msg)
149{
150 if (msg->msg_message != NULL) {
151 mmap_string_unref(msg->msg_message);
152 msg->msg_message = NULL;
153 }
154}
155
156static int mbox_initialize(mailmessage * msg_info)
157{
158 struct generic_message_t * msg;
159 int r;
160 char * uid;
161 char static_uid[PATH_MAX];
162 struct mailmbox_msg_info * info;
163 struct mailmbox_folder * folder;
164 int res;
165 chashdatum key;
166 chashdatum data;
167
168 folder = get_mbox_session(msg_info);
169 if (folder == NULL) {
170 res = MAIL_ERROR_BAD_STATE;
171 goto err;
172 }
173
174 key.data = (char *) &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176
177 r = chash_get(folder->mb_hash, &key, &data);
178 if (r < 0) {
179 res = MAIL_ERROR_MSG_NOT_FOUND;
180 goto err;
181 }
182
183 info = (struct mailmbox_msg_info *) data.data;
184
185 snprintf(static_uid, PATH_MAX, "%u-%lu",
186 msg_info->msg_index, (unsigned long) info->msg_body_len);
187 uid = strdup(static_uid);
188 if (uid == NULL) {
189 res = MAIL_ERROR_MEMORY;
190 goto err;
191 }
192
193 r = mailmessage_generic_initialize(msg_info);
194 if (r != MAIL_NO_ERROR) {
195 free(uid);
196 res = r;
197 goto err;
198 }
199
200 msg = msg_info->msg_data;
201
202 msg->msg_prefetch = mbox_prefetch;
203 msg->msg_prefetch_free = mbox_prefetch_free;
204 msg_info->msg_uid = uid;
205
206 return MAIL_NO_ERROR;
207
208 err:
209 return res;
210}
211
212static void mbox_uninitialize(mailmessage * msg_info)
213{
214 mailmessage_generic_uninitialize(msg_info);
215}
216
217#define FLAGS_NAME "flags.db"
218
219static void mbox_flush(mailmessage * msg_info)
220{
221 mailmessage_generic_flush(msg_info);
222}
223
224static void mbox_check(mailmessage * msg_info)
225{
226 int r;
227
228 if (msg_info->msg_flags != NULL) {
229 r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store,
230 msg_info);
231 /* ignore errors */
232 }
233}
234
235
236static int mbox_fetch_size(mailmessage * msg_info,
237 size_t * result)
238{
239 int r;
240 size_t size;
241
242 r = mboxdriver_fetch_size(get_ancestor_session(msg_info),
243 msg_info->msg_index, &size);
244 if (r != MAIL_NO_ERROR)
245 return r;
246
247 * result = size;
248
249 return MAIL_NO_ERROR;
250}
251
252static int mbox_get_flags(mailmessage * msg_info,
253 struct mail_flags ** result)
254{
255 int r;
256 struct mail_flags * flags;
257 struct mail_cache_db * cache_db_flags;
258 char filename_flags[PATH_MAX];
259 int res;
260 struct mbox_cached_session_state_data * cached_data;
261 MMAPString * mmapstr;
262 struct mailmbox_folder * folder;
263
264 if (msg_info->msg_flags != NULL) {
265 * result = msg_info->msg_flags;
266
267 return MAIL_NO_ERROR;
268 }
269
270 flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store,
271 msg_info->msg_index);
272
273 if (flags == NULL) {
274 folder = get_mbox_session(msg_info);
275 if (folder == NULL) {
276 res = MAIL_ERROR_BAD_STATE;
277 goto err;
278 }
279
280 cached_data = get_cached_session_data(msg_info);
281 if (cached_data->mbox_quoted_mb == NULL) {
282 res = MAIL_ERROR_BAD_STATE;
283 goto err;
284 }
285
286 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
287 cached_data->mbox_flags_directory,
288 cached_data->mbox_quoted_mb, FLAGS_NAME);
289
290 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
291 if (r < 0) {
292 res = MAIL_ERROR_MEMORY;
293 goto err;
294 }
295
296 mmapstr = mmap_string_new("");
297 if (mmapstr == NULL) {
298 res = MAIL_ERROR_MEMORY;
299 goto close_db_flags;
300 }
301
302 if (msg_info->msg_index > folder->mb_written_uid) {
303 flags = mail_flags_new_empty();
304 }
305 else {
306 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
307 msg_info->msg_session,
308 msg_info->msg_index, &flags);
309 if (r != MAIL_NO_ERROR) {
310 flags = mail_flags_new_empty();
311 if (flags == NULL) {
312 res = MAIL_ERROR_MEMORY;
313 goto free_mmapstr;
314 }
315 }
316 }
317
318 mmap_string_free(mmapstr);
319 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
320 }
321
322 msg_info->msg_flags = flags;
323
324 * result = flags;
325
326 return MAIL_NO_ERROR;
327
328 free_mmapstr:
329 mmap_string_free(mmapstr);
330 close_db_flags:
331 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
332 err:
333 return res;
334}
335
336static int mbox_fetch_header(mailmessage * msg_info,
337 char ** result,
338 size_t * result_len)
339{
340 struct generic_message_t * msg;
341 int r;
342 char * msg_content;
343 size_t msg_length;
344
345 msg = msg_info->msg_data;
346 if (msg->msg_message != NULL) {
347 return mailmessage_generic_fetch_header(msg_info, result, result_len);
348 }
349 else {
350 r = mboxdriver_fetch_header(get_ancestor_session(msg_info),
351 msg_info->msg_index,
352 &msg_content, &msg_length);
353 if (r != MAIL_NO_ERROR)
354 return r;
355
356 * result = msg_content;
357 * result_len = msg_length;
358
359 return MAIL_NO_ERROR;
360 }
361}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h
new file mode 100644
index 0000000..144e2da
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_CACHED_MESSAGE_H
37
38#define MBOXDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mailmessage.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c
new file mode 100644
index 0000000..9bb5a18
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.c
@@ -0,0 +1,225 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver.h"
41#include "mailmbox.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int mbox_prefetch(mailmessage * msg_info);
52
53static void mbox_prefetch_free(struct generic_message_t * msg);
54
55static int mbox_initialize(mailmessage * msg_info);
56
57static int mbox_fetch_size(mailmessage * msg_info,
58 size_t * result);
59
60static int mbox_fetch_header(mailmessage * msg_info,
61 char ** result,
62 size_t * result_len);
63
64static mailmessage_driver local_mbox_message_driver = {
65 .msg_name = "mbox",
66
67 .msg_initialize = mbox_initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = NULL,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mbox_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_body,
78 .msg_fetch_size = mbox_fetch_size,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = NULL,
87};
88
89mailmessage_driver * mbox_message_driver = &local_mbox_message_driver;
90
91static inline struct mbox_session_state_data * get_data(mailmessage * msg)
92{
93 return msg->msg_session->sess_data;
94}
95
96static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg)
97{
98 return get_data(msg)->mbox_folder;
99}
100
101
102static int mbox_prefetch(mailmessage * msg_info)
103{
104 struct generic_message_t * msg;
105 int r;
106 char * msg_content;
107 size_t msg_length;
108
109 r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index,
110 &msg_content, &msg_length);
111 if (r != MAIL_NO_ERROR)
112 return r;
113
114 msg = msg_info->msg_data;
115
116 msg->msg_message = msg_content;
117 msg->msg_length = msg_length;
118
119 return MAIL_NO_ERROR;
120}
121
122static void mbox_prefetch_free(struct generic_message_t * msg)
123{
124 if (msg->msg_message != NULL) {
125 mmap_string_unref(msg->msg_message);
126 msg->msg_message = NULL;
127 }
128}
129
130static int mbox_initialize(mailmessage * msg_info)
131{
132 struct generic_message_t * msg;
133 int r;
134 char * uid;
135 char static_uid[PATH_MAX];
136 struct mailmbox_msg_info * info;
137 struct mailmbox_folder * folder;
138 int res;
139 chashdatum key;
140 chashdatum data;
141
142 folder = get_mbox_session(msg_info);
143 if (folder == NULL) {
144 res = MAIL_ERROR_BAD_STATE;
145 goto err;
146 }
147
148 key.data = &msg_info->msg_index;
149 key.len = sizeof(msg_info->msg_index);
150
151 r = chash_get(folder->mb_hash, &key, &data);
152 if (r < 0) {
153 res = MAIL_ERROR_MSG_NOT_FOUND;
154 goto err;
155 }
156
157 info = data.data;
158
159 snprintf(static_uid, PATH_MAX, "%u-%lu",
160 msg_info->msg_index, (unsigned long) info->msg_body_len);
161 uid = strdup(static_uid);
162 if (uid == NULL) {
163 res = MAIL_ERROR_MEMORY;
164 goto err;
165 }
166
167 r = mailmessage_generic_initialize(msg_info);
168 if (r != MAIL_NO_ERROR) {
169 free(uid);
170 res = r;
171 goto err;
172 }
173
174 msg = msg_info->msg_data;
175 msg->msg_prefetch = mbox_prefetch;
176 msg->msg_prefetch_free = mbox_prefetch_free;
177 msg_info->msg_uid = uid;
178
179 return MAIL_NO_ERROR;
180
181 err:
182 return res;
183}
184
185static int mbox_fetch_size(mailmessage * msg_info,
186 size_t * result)
187{
188 int r;
189 size_t size;
190
191 r = mboxdriver_fetch_size(msg_info->msg_session,
192 msg_info->msg_index, &size);
193 if (r != MAIL_NO_ERROR)
194 return r;
195
196 * result = size;
197
198 return MAIL_NO_ERROR;
199}
200
201static int mbox_fetch_header(mailmessage * msg_info,
202 char ** result,
203 size_t * result_len)
204{
205 struct generic_message_t * msg;
206 int r;
207 char * msg_content;
208 size_t msg_length;
209
210 msg = msg_info->msg_data;
211 if (msg->msg_message != NULL) {
212 return mailmessage_generic_fetch_header(msg_info, result, result_len);
213 }
214 else {
215 r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
216 &msg_content, &msg_length);
217 if (r != MAIL_NO_ERROR)
218 return r;
219
220 * result = msg_content;
221 * result_len = msg_length;
222
223 return MAIL_NO_ERROR;
224 }
225}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_message.h b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h
new file mode 100644
index 0000000..686e46e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_MESSAGE_H
37
38#define MBOXDRIVER_MESSAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mbox_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
new file mode 100644
index 0000000..dc38cbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
@@ -0,0 +1,435 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_tools.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42
43#include "maildriver_types.h"
44#include "mailmbox.h"
45#include "mboxdriver_cached.h"
46#include "mboxdriver.h"
47#include "generic_cache.h"
48#include "mailmessage.h"
49#include "imfcache.h"
50#include "mail_cache_db.h"
51
52static inline struct mbox_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct mailmbox_folder *
59session_get_mbox_session(mailsession * session)
60{
61 return session_get_data(session)->mbox_folder;
62}
63
64static inline struct mbox_cached_session_state_data *
65cached_session_get_data(mailsession * session)
66{
67 return session->sess_data;
68}
69
70static inline mailsession *
71cached_session_get_ancestor(mailsession * session)
72{
73 return cached_session_get_data(session)->mbox_ancestor;
74}
75
76static inline struct mbox_session_state_data *
77cached_session_get_ancestor_data(mailsession * session)
78{
79 return cached_session_get_ancestor(session)->sess_data;
80}
81
82static inline struct mailmbox_folder *
83cached_session_get_mbox_session(mailsession * session)
84{
85 return session_get_mbox_session(cached_session_get_ancestor(session));
86}
87
88
89int mboxdriver_mbox_error_to_mail_error(int error)
90{
91 switch (error) {
92 case MAILMBOX_NO_ERROR:
93 return MAIL_NO_ERROR;
94
95 case MAILMBOX_ERROR_PARSE:
96 return MAIL_ERROR_PARSE;
97
98 case MAILMBOX_ERROR_INVAL:
99 return MAIL_ERROR_INVAL;
100
101 case MAILMBOX_ERROR_FILE_NOT_FOUND:
102 return MAIL_ERROR_PARSE;
103
104 case MAILMBOX_ERROR_MEMORY:
105 return MAIL_ERROR_MEMORY;
106
107 case MAILMBOX_ERROR_TEMPORARY_FILE:
108 return MAIL_ERROR_PARSE;
109
110 case MAILMBOX_ERROR_FILE:
111 return MAIL_ERROR_FILE;
112
113 case MAILMBOX_ERROR_MSG_NOT_FOUND:
114 return MAIL_ERROR_MSG_NOT_FOUND;
115
116 case MAILMBOX_ERROR_READONLY:
117 return MAIL_ERROR_READONLY;
118
119 default:
120 return MAIL_ERROR_INVAL;
121 }
122}
123
124int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
125 char ** result, size_t * result_len)
126{
127 int r;
128 char * msg_content;
129 size_t msg_length;
130 struct mailmbox_folder * folder;
131
132 folder = session_get_mbox_session(session);
133 if (folder == NULL)
134 return MAIL_ERROR_BAD_STATE;
135
136 r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length);
137 if (r != MAILMBOX_NO_ERROR)
138 return mboxdriver_mbox_error_to_mail_error(r);
139
140 * result = msg_content;
141 * result_len = msg_length;
142
143 return MAIL_NO_ERROR;
144}
145
146
147int mboxdriver_fetch_size(mailsession * session, uint32_t index,
148 size_t * result)
149{
150 struct mailmbox_folder * folder;
151 int r;
152 char * data;
153 size_t len;
154 int res;
155
156 folder = session_get_mbox_session(session);
157 if (folder == NULL) {
158 res = MAIL_ERROR_FETCH;
159 goto err;
160 }
161
162 r = mailmbox_validate_read_lock(folder);
163 if (r != MAILMBOX_NO_ERROR) {
164 res = mboxdriver_mbox_error_to_mail_error(r);
165 goto err;
166 }
167
168 r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len);
169 if (r != MAILMBOX_NO_ERROR) {
170 res = mboxdriver_mbox_error_to_mail_error(r);
171 goto unlock;
172 }
173
174 mailmbox_read_unlock(folder);
175
176 * result = len;
177
178 return MAIL_NO_ERROR;
179
180 unlock:
181 mailmbox_read_unlock(folder);
182 err:
183 return res;
184}
185
186
187int
188mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
189 MMAPString * mmapstr,
190 mailsession * session,
191 uint32_t num,
192 struct mail_flags ** result)
193{
194 int r;
195 char keyname[PATH_MAX];
196 struct mail_flags * flags;
197 int res;
198 struct mailmbox_msg_info * info;
199 struct mailmbox_folder * folder;
200 chashdatum key;
201 chashdatum data;
202
203 folder = cached_session_get_mbox_session(session);
204 if (folder == NULL) {
205 res = MAIL_ERROR_BAD_STATE;
206 goto err;
207 }
208
209 key.data = &num;
210 key.len = sizeof(num);
211
212 r = chash_get(folder->mb_hash, &key, &data);
213 if (r < 0) {
214 res = MAIL_ERROR_MSG_NOT_FOUND;
215 goto err;
216 }
217
218 info = data.data;
219
220 snprintf(keyname, PATH_MAX, "%u-%lu-flags", num,
221 (unsigned long) info->msg_body_len);
222
223 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
224 if (r != MAIL_NO_ERROR) {
225 res = r;
226 goto err;
227 }
228
229 * result = flags;
230
231 return MAIL_NO_ERROR;
232
233 err:
234 return res;
235}
236
237int
238mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
239 MMAPString * mmapstr,
240 char * uid,
241 struct mail_flags * flags)
242{
243 int r;
244 char keyname[PATH_MAX];
245 int res;
246
247 snprintf(keyname, PATH_MAX, "%s-flags", uid);
248
249 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
250 if (r != MAIL_NO_ERROR) {
251 res = r;
252 goto err;
253 }
254
255 return MAIL_NO_ERROR;
256
257 err:
258 return res;
259}
260
261
262int mboxdriver_fetch_header(mailsession * session, uint32_t index,
263 char ** result, size_t * result_len)
264{
265 int r;
266 char * msg_content;
267 size_t msg_length;
268 struct mailmbox_folder * folder;
269
270 folder = session_get_mbox_session(session);
271 if (folder == NULL)
272 return MAIL_ERROR_BAD_STATE;
273
274 r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length);
275 if (r != MAILMBOX_NO_ERROR)
276 return mboxdriver_mbox_error_to_mail_error(r);
277
278 * result = msg_content;
279 * result_len = msg_length;
280
281 return MAIL_NO_ERROR;
282}
283
284int mbox_get_locked_messages_list(struct mailmbox_folder * folder,
285 mailsession * session,
286 mailmessage_driver * driver,
287 int (* lock)(struct mailmbox_folder *),
288 int (* unlock)(struct mailmbox_folder *),
289 struct mailmessage_list ** result)
290{
291 struct mailmessage_list * env_list;
292 unsigned int i;
293 int r;
294 int res;
295 carray * tab;
296
297 tab = carray_new(128);
298 if (tab == NULL) {
299 res = MAIL_ERROR_MEMORY;
300 goto err;
301 }
302
303 r = lock(folder);
304 if (r != MAIL_NO_ERROR) {
305 res = r;
306 goto free;
307 }
308
309 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
310 struct mailmbox_msg_info * msg_info;
311 mailmessage * msg;
312
313 msg_info = carray_get(folder->mb_tab, i);
314 if (msg_info == NULL)
315 continue;
316
317 if (msg_info->msg_deleted)
318 continue;
319
320 msg = mailmessage_new();
321 if (msg == NULL) {
322 res = MAIL_ERROR_MEMORY;
323 goto unlock;
324 }
325
326 r = mailmessage_init(msg, session, driver, msg_info->msg_uid,
327 msg_info->msg_size - msg_info->msg_start_len);
328 if (r != MAIL_NO_ERROR) {
329 res = r;
330 goto unlock;
331 }
332
333 r = carray_add(tab, msg, NULL);
334 if (r < 0) {
335 mailmessage_free(msg);
336 res = MAIL_ERROR_MEMORY;
337 goto unlock;
338 }
339 }
340
341 env_list = mailmessage_list_new(tab);
342 if (env_list == NULL) {
343 res = MAIL_ERROR_MEMORY;
344 goto unlock;
345 }
346
347 unlock(folder);
348
349 * result = env_list;
350
351 return MAIL_NO_ERROR;
352
353 unlock:
354 unlock(folder);
355 free:
356 for(i = 0 ; i < carray_count(tab) ; i ++)
357 mailmessage_free(carray_get(tab, i));
358 carray_free(tab);
359 err:
360 return res;
361}
362
363static int release_read_mbox(struct mailmbox_folder * folder)
364{
365 int r;
366
367 r = mailmbox_read_unlock(folder);
368 return mboxdriver_mbox_error_to_mail_error(r);
369}
370
371static int acquire_read_mbox(struct mailmbox_folder * folder)
372{
373 int r;
374
375 r = mailmbox_validate_read_lock(folder);
376 return mboxdriver_mbox_error_to_mail_error(r);
377}
378
379static int release_write_mbox(struct mailmbox_folder * folder)
380{
381 int r;
382
383 r = mailmbox_write_unlock(folder);
384 return mboxdriver_mbox_error_to_mail_error(r);
385}
386
387static int acquire_write_mbox(struct mailmbox_folder * folder)
388{
389 int r;
390 int res;
391
392 r = mailmbox_validate_write_lock(folder);
393 if (r != MAILMBOX_NO_ERROR) {
394 res = mboxdriver_mbox_error_to_mail_error(r);
395 goto err;
396 }
397
398 if (folder->mb_written_uid < folder->mb_max_uid) {
399 r = mailmbox_expunge_no_lock(folder);
400 if (r != MAILMBOX_NO_ERROR) {
401 res = mboxdriver_mbox_error_to_mail_error(r);
402 goto unlock;
403 }
404 }
405
406 return MAIL_NO_ERROR;
407
408 unlock:
409 mailmbox_write_unlock(folder);
410 err:
411 return res;
412}
413
414/* get message list with all valid written UID */
415
416int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
417 mailsession * session,
418 mailmessage_driver * driver,
419 struct mailmessage_list ** result)
420{
421 return mbox_get_locked_messages_list(folder, session, driver,
422 acquire_write_mbox, release_write_mbox, result);
423}
424
425
426/* get message list */
427
428int mbox_get_messages_list(struct mailmbox_folder * folder,
429 mailsession * session,
430 mailmessage_driver * driver,
431 struct mailmessage_list ** result)
432{
433 return mbox_get_locked_messages_list(folder, session, driver,
434 acquire_read_mbox, release_read_mbox, result);
435}
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h
new file mode 100644
index 0000000..eebf98c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h
@@ -0,0 +1,85 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_TOOLS_H
37
38#define MBOXDRIVER_TOOLS_H
39
40#include "mail_cache_db_types.h"
41#include "mboxdriver_types.h"
42#include "mailmbox.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int mboxdriver_mbox_error_to_mail_error(int error);
49
50int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int mboxdriver_fetch_size(mailsession * session, uint32_t index,
54 size_t * result);
55
56int
57mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
58 MMAPString * mmapstr,
59 mailsession * session,
60 uint32_t num,
61 struct mail_flags ** result);
62
63int
64mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
65 MMAPString * mmapstr,
66 char * uid, struct mail_flags * flags);
67
68int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
69 mailsession * session,
70 mailmessage_driver * driver,
71 struct mailmessage_list ** result);
72
73int mbox_get_messages_list(struct mailmbox_folder * folder,
74 mailsession * session,
75 mailmessage_driver * driver,
76 struct mailmessage_list ** result);
77
78int mboxdriver_fetch_header(mailsession * session, uint32_t index,
79 char ** result, size_t * result_len);
80
81#ifdef __cplusplus
82}
83#endif
84
85#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_types.h b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h
new file mode 100644
index 0000000..23b9acf
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_types.h
@@ -0,0 +1,107 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXDRIVER_TYPES_H
37
38#define MBOXDRIVER_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailmbox.h>
42#include <libetpan/mailstorage_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/* mbox driver */
49
50enum {
51 MBOXDRIVER_SET_READ_ONLY = 1,
52 MBOXDRIVER_SET_NO_UID,
53};
54
55struct mbox_session_state_data {
56 struct mailmbox_folder * mbox_folder;
57 int mbox_force_read_only;
58 int mbox_force_no_uid;
59};
60
61/* cached version */
62
63enum {
64 /* the mapping of the parameters should be the same as for mbox */
65 MBOXDRIVER_CACHED_SET_READ_ONLY = 1,
66 MBOXDRIVER_CACHED_SET_NO_UID,
67 /* cache specific */
68 MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
69 MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
70};
71
72struct mbox_cached_session_state_data {
73 mailsession * mbox_ancestor;
74 char * mbox_quoted_mb;
75 char mbox_cache_directory[PATH_MAX];
76 char mbox_flags_directory[PATH_MAX];
77 struct mail_flags_store * mbox_flags_store;
78};
79
80/* mbox storage */
81
82/*
83 mbox_mailstorage is the state data specific to the mbox storage.
84
85 - pathname is the filename that contains the mailbox.
86
87 - cached if this value is != 0, a persistant cache will be
88 stored on local system.
89
90 - cache_directory is the location of the cache.
91
92 - flags_directory is the location of the flags.
93*/
94
95struct mbox_mailstorage {
96 char * mbox_pathname;
97
98 int mbox_cached;
99 char * mbox_cache_directory;
100 char * mbox_flags_directory;
101};
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif
diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.c b/libetpan/src/driver/implementation/mbox/mboxstorage.c
new file mode 100644
index 0000000..3944c3b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxstorage.c
@@ -0,0 +1,192 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxstorage.h"
37
38#include "mail.h"
39#include "mailmessage.h"
40#include "mboxdriver.h"
41#include "mboxdriver_cached.h"
42#include "maildriver.h"
43
44#include <stdlib.h>
45#include <string.h>
46
47/* mbox storage */
48
49static int mbox_mailstorage_connect(struct mailstorage * storage);
50static int
51mbox_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void mbox_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver mbox_mailstorage_driver = {
56 .sto_name = "mbox",
57 .sto_connect = mbox_mailstorage_connect,
58 .sto_get_folder_session = mbox_mailstorage_get_folder_session,
59 .sto_uninitialize = mbox_mailstorage_uninitialize,
60};
61
62int mbox_mailstorage_init(struct mailstorage * storage,
63 char * mbox_pathname, int mbox_cached,
64 char * mbox_cache_directory, char * mbox_flags_directory)
65{
66 struct mbox_mailstorage * mbox_storage;
67
68 mbox_storage = malloc(sizeof(* mbox_storage));
69 if (mbox_storage == NULL)
70 goto err;
71
72 mbox_storage->mbox_pathname = strdup(mbox_pathname);
73 if (mbox_storage->mbox_pathname == NULL)
74 goto free;
75
76 mbox_storage->mbox_cached = mbox_cached;
77
78 if (mbox_cached && (mbox_cache_directory != NULL) &&
79 (mbox_flags_directory != NULL)) {
80 mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory);
81 if (mbox_storage->mbox_cache_directory == NULL)
82 goto free_pathname;
83
84 mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory);
85 if (mbox_storage->mbox_flags_directory == NULL)
86 goto free_cache_directory;
87 }
88 else {
89 mbox_storage->mbox_cached = FALSE;
90 mbox_storage->mbox_cache_directory = NULL;
91 mbox_storage->mbox_flags_directory = NULL;
92 }
93
94 storage->sto_data = mbox_storage;
95 storage->sto_driver = &mbox_mailstorage_driver;
96
97 return MAIL_NO_ERROR;
98
99 free_cache_directory:
100 free(mbox_storage->mbox_cache_directory);
101 free_pathname:
102 free(mbox_storage->mbox_pathname);
103 free:
104 free(mbox_storage);
105 err:
106 return MAIL_ERROR_MEMORY;
107}
108
109static void mbox_mailstorage_uninitialize(struct mailstorage * storage)
110{
111 struct mbox_mailstorage * mbox_storage;
112
113 mbox_storage = storage->sto_data;
114 if (mbox_storage->mbox_flags_directory != NULL)
115 free(mbox_storage->mbox_flags_directory);
116 if (mbox_storage->mbox_cache_directory != NULL)
117 free(mbox_storage->mbox_cache_directory);
118 free(mbox_storage->mbox_pathname);
119 free(mbox_storage);
120
121 storage->sto_data = NULL;
122}
123
124static int mbox_mailstorage_connect(struct mailstorage * storage)
125{
126 struct mbox_mailstorage * mbox_storage;
127 mailsession_driver * driver;
128 int r;
129 int res;
130 mailsession * session;
131
132 mbox_storage = storage->sto_data;
133
134 if (mbox_storage->mbox_cached)
135 driver = mbox_cached_session_driver;
136 else
137 driver = mbox_session_driver;
138
139 session = mailsession_new(driver);
140 if (session == NULL) {
141 res = MAIL_ERROR_MEMORY;
142 goto err;
143 }
144
145 if (mbox_storage->mbox_cached) {
146 r = mailsession_parameters(session,
147 MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY,
148 mbox_storage->mbox_cache_directory);
149 if (r != MAIL_NO_ERROR) {
150 res = r;
151 goto free;
152 }
153
154 r = mailsession_parameters(session,
155 MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY,
156 mbox_storage->mbox_flags_directory);
157 if (r != MAIL_NO_ERROR) {
158 res = r;
159 goto free;
160 }
161 }
162
163 r = mailsession_connect_path(session, mbox_storage->mbox_pathname);
164 switch (r) {
165 case MAIL_NO_ERROR_NON_AUTHENTICATED:
166 case MAIL_NO_ERROR_AUTHENTICATED:
167 case MAIL_NO_ERROR:
168 break;
169 default:
170 res = r;
171 goto free;
172 }
173
174 storage->sto_session = session;
175
176 return MAIL_NO_ERROR;
177
178 free:
179 mailsession_free(session);
180 err:
181 return res;
182}
183
184static int
185mbox_mailstorage_get_folder_session(struct mailstorage * storage,
186 char * pathname, mailsession ** result)
187{
188 * result = storage->sto_session;
189
190 return MAIL_NO_ERROR;
191}
192
diff --git a/libetpan/src/driver/implementation/mbox/mboxstorage.h b/libetpan/src/driver/implementation/mbox/mboxstorage.h
new file mode 100644
index 0000000..45aed7b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxstorage.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MBOXSTORAGE_H
37
38#define MBOXSTORAGE_H
39
40#include <libetpan/mboxdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mbox_mailstorage_init is the constructor for a mbox storage.
48
49 @param storage this is the storage to initialize.
50
51 @param pathname is the filename that contains the mailbox.
52
53 @param cached if this value is != 0, a persistant cache will be
54 stored on local system.
55
56 @param cache_directory is the location of the cache
57
58 @param flags_directory is the location of the flags
59*/
60
61int mbox_mailstorage_init(struct mailstorage * storage,
62 char * mb_pathname, int mb_cached,
63 char * mb_cache_directory, char * mb_flags_directory);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver.c b/libetpan/src/driver/implementation/mh/mhdriver.c
new file mode 100644
index 0000000..c44afc9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver.c
@@ -0,0 +1,875 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mailmh.h"
50#include "maildriver_tools.h"
51#include "mhdriver_tools.h"
52#include "mhdriver_message.h"
53#include "mailmessage.h"
54
55static int mhdriver_initialize(mailsession * session);
56
57static void mhdriver_uninitialize(mailsession * session);
58
59static int mhdriver_connect_path(mailsession * session, char * path);
60static int mhdriver_logout(mailsession * session);
61
62static int mhdriver_build_folder_name(mailsession * session, char * mb,
63 char * name, char ** result);
64static int mhdriver_create_folder(mailsession * session, char * mb);
65
66static int mhdriver_delete_folder(mailsession * session, char * mb);
67
68static int mhdriver_rename_folder(mailsession * session, char * mb,
69 char * new_name);
70
71static int mhdriver_select_folder(mailsession * session, char * mb);
72
73static int mhdriver_status_folder(mailsession * session, char * mb,
74 uint32_t * result_messages, uint32_t * result_recent,
75 uint32_t * result_unseen);
76
77static int mhdriver_messages_number(mailsession * session, char * mb,
78 uint32_t * result);
79
80static int mhdriver_list_folders(mailsession * session, char * mb,
81 struct mail_list ** result);
82
83static int mhdriver_lsub_folders(mailsession * session, char * mb,
84 struct mail_list ** result);
85
86static int mhdriver_subscribe_folder(mailsession * session, char * mb);
87
88static int mhdriver_unsubscribe_folder(mailsession * session, char * mb);
89
90static int mhdriver_append_message(mailsession * session,
91 char * message, size_t size);
92static int mhdriver_append_message_flags(mailsession * session,
93 char * message, size_t size, struct mail_flags * flags);
94static int mhdriver_copy_message(mailsession * session,
95 uint32_t num, char * mb);
96
97static int mhdriver_remove_message(mailsession * session, uint32_t num);
98
99static int mhdriver_move_message(mailsession * session,
100 uint32_t num, char * mb);
101
102static int mhdriver_get_messages_list(mailsession * session,
103 struct mailmessage_list ** result);
104
105static int mhdriver_get_message(mailsession * session,
106 uint32_t num, mailmessage ** result);
107
108static int mhdriver_get_message_by_uid(mailsession * session,
109 const char * uid,
110 mailmessage ** result);
111
112static mailsession_driver local_mh_session_driver = {
113 .sess_name = "mh",
114
115 .sess_initialize = mhdriver_initialize,
116 .sess_uninitialize = mhdriver_uninitialize,
117
118 .sess_parameters = NULL,
119
120 .sess_connect_stream = NULL,
121 .sess_connect_path = mhdriver_connect_path,
122 .sess_starttls = NULL,
123 .sess_login = NULL,
124 .sess_logout = mhdriver_logout,
125 .sess_noop = NULL,
126
127 .sess_build_folder_name = mhdriver_build_folder_name,
128 .sess_create_folder = mhdriver_create_folder,
129 .sess_delete_folder = mhdriver_delete_folder,
130 .sess_rename_folder = mhdriver_rename_folder,
131 .sess_check_folder = NULL,
132 .sess_examine_folder = NULL,
133 .sess_select_folder = mhdriver_select_folder,
134 .sess_expunge_folder = NULL,
135 .sess_status_folder = mhdriver_status_folder,
136 .sess_messages_number = mhdriver_messages_number,
137 .sess_recent_number = mhdriver_messages_number,
138 .sess_unseen_number = mhdriver_messages_number,
139 .sess_list_folders = mhdriver_list_folders,
140 .sess_lsub_folders = mhdriver_lsub_folders,
141 .sess_subscribe_folder = mhdriver_subscribe_folder,
142 .sess_unsubscribe_folder = mhdriver_unsubscribe_folder,
143
144 .sess_append_message = mhdriver_append_message,
145 .sess_append_message_flags = mhdriver_append_message_flags,
146 .sess_copy_message = mhdriver_copy_message,
147 .sess_move_message = mhdriver_move_message,
148
149 .sess_get_messages_list = mhdriver_get_messages_list,
150 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
151 .sess_remove_message = mhdriver_remove_message,
152#if 0
153 .sess_search_messages = maildriver_generic_search_messages,
154#endif
155
156 .sess_get_message = mhdriver_get_message,
157 .sess_get_message_by_uid = mhdriver_get_message_by_uid,
158};
159
160mailsession_driver * mh_session_driver = &local_mh_session_driver;
161
162static inline struct mh_session_state_data * get_data(mailsession * session)
163{
164 return session->sess_data;
165}
166
167static inline struct mailmh * get_mh_session(mailsession * session)
168{
169 return get_data(session)->mh_session;
170}
171
172static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
173{
174 return get_data(session)->mh_cur_folder;
175}
176
177static int add_to_list(mailsession * session, char * mb)
178{
179 char * new_mb;
180 struct mh_session_state_data * data;
181 int r;
182
183 data = get_data(session);
184
185 new_mb = strdup(mb);
186 if (new_mb == NULL)
187 return -1;
188
189 r = clist_append(data->mh_subscribed_list, new_mb);
190 if (r < 0) {
191 free(mb);
192 return -1;
193 }
194
195 return 0;
196}
197
198static int remove_from_list(mailsession * session, char * mb)
199{
200 clistiter * cur;
201 struct mh_session_state_data * data;
202
203 data = get_data(session);
204
205 for(cur = clist_begin(data->mh_subscribed_list) ;
206 cur != NULL ; cur = clist_next(cur)) {
207 char * cur_name;
208
209 cur_name = clist_content(cur);
210 if (strcmp(cur_name, mb) == 0) {
211 clist_delete(data->mh_subscribed_list, cur);
212 free(cur_name);
213 return 0;
214 }
215 }
216
217 return -1;
218}
219
220static int mhdriver_initialize(mailsession * session)
221{
222 struct mh_session_state_data * data;
223
224 data = malloc(sizeof(* data));
225 if (data == NULL)
226 goto err;
227
228 data->mh_session = NULL;
229 data->mh_cur_folder = NULL;
230
231 data->mh_subscribed_list = clist_new();
232 if (data->mh_subscribed_list == NULL)
233 goto free;
234
235 session->sess_data = data;
236
237 return MAIL_NO_ERROR;
238
239 free:
240 free(data);
241 err:
242 return MAIL_ERROR_MEMORY;
243}
244
245static void mhdriver_uninitialize(mailsession * session)
246{
247 struct mh_session_state_data * data;
248
249 data = get_data(session);
250
251 if (data->mh_session != NULL)
252 mailmh_free(data->mh_session);
253
254 clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL);
255 clist_free(data->mh_subscribed_list);
256
257 free(data);
258
259 session->sess_data = NULL;
260}
261
262
263static int mhdriver_connect_path(mailsession * session, char * path)
264{
265 struct mailmh * mh;
266
267 if (get_mh_session(session) != NULL)
268 return MAIL_ERROR_BAD_STATE;
269
270 mh = mailmh_new(path);
271 if (mh == NULL)
272 return MAIL_ERROR_MEMORY;
273
274 get_data(session)->mh_session = mh;
275
276 return MAIL_NO_ERROR;
277}
278
279static int mhdriver_logout(mailsession * session)
280{
281 struct mailmh * mh;
282
283 mh = get_mh_session(session);
284
285 if (mh == NULL)
286 return MAIL_ERROR_BAD_STATE;
287
288 mailmh_free(mh);
289 get_data(session)->mh_session = NULL;
290
291 return MAIL_NO_ERROR;
292}
293
294/* folders operations */
295
296static int mhdriver_build_folder_name(mailsession * session, char * mb,
297 char * name, char ** result)
298{
299 char * folder_name;
300
301 folder_name = malloc(strlen(mb) + 2 + strlen(name));
302 if (folder_name == NULL)
303 return MAIL_ERROR_MEMORY;
304
305 strcpy(folder_name, mb);
306 strcat(folder_name, "/");
307 strcat(folder_name, name);
308
309 * result = folder_name;
310
311 return MAIL_NO_ERROR;
312}
313
314static int get_parent(mailsession * session, char * mb,
315 struct mailmh_folder ** result_folder,
316 char ** result_name)
317{
318 char * name;
319 size_t length;
320 int i;
321 char * parent_name;
322 struct mailmh_folder * parent;
323 struct mailmh * mh;
324
325 mh = get_mh_session(session);
326 if (mh == NULL)
327 return MAIL_ERROR_BAD_STATE;
328
329 length = strlen(mb);
330 for(i = length - 1 ; i >= 0 ; i--)
331 if (mb[i] == '/')
332 break;
333 name = mb + i + 1;
334
335 parent_name = malloc(i + 1);
336 /* strndup(mb, i) */
337 if (parent_name == NULL)
338 return MAIL_ERROR_MEMORY;
339
340 strncpy(parent_name, mb, i);
341 parent_name[i] = '\0';
342
343 parent = mailmh_folder_find(mh->mh_main, parent_name);
344 free(parent_name);
345 if (parent == NULL)
346 return MAIL_ERROR_FOLDER_NOT_FOUND;
347
348 * result_folder = parent;
349 * result_name = name;
350
351 return MAIL_NO_ERROR;
352}
353
354static int mhdriver_create_folder(mailsession * session, char * mb)
355{
356 int r;
357 struct mailmh_folder * parent;
358 char * name;
359
360 r = get_parent(session, mb, &parent, &name);
361 if (r != MAIL_NO_ERROR)
362 return r;
363
364 r = mailmh_folder_add_subfolder(parent, name);
365
366 return mhdriver_mh_error_to_mail_error(r);
367}
368
369static int mhdriver_delete_folder(mailsession * session, char * mb)
370{
371 int r;
372 struct mailmh_folder * folder;
373 struct mailmh * mh;
374
375 mh = get_mh_session(session);
376 if (mh == NULL)
377 return MAIL_ERROR_BAD_STATE;
378
379 folder = mailmh_folder_find(mh->mh_main, mb);
380 if (folder == NULL)
381 return MAIL_ERROR_FOLDER_NOT_FOUND;
382
383 if (get_mh_cur_folder(session) == folder)
384 get_data(session)->mh_cur_folder = NULL;
385
386 r = mailmh_folder_remove_subfolder(folder);
387
388 return mhdriver_mh_error_to_mail_error(r);
389}
390
391static int mhdriver_rename_folder(mailsession * session, char * mb,
392 char * new_name)
393{
394 struct mailmh_folder * src_folder;
395 struct mailmh_folder * dst_folder;
396 char * name;
397 struct mailmh * mh;
398 int r;
399
400 r = get_parent(session, new_name, &dst_folder, &name);
401 if (r != MAIL_NO_ERROR)
402 return r;
403
404 mh = get_mh_session(session);
405 if (mh == NULL)
406 return MAIL_ERROR_BAD_STATE;
407
408 src_folder = mailmh_folder_find(mh->mh_main, mb);
409 if (src_folder == NULL)
410 return MAIL_ERROR_FOLDER_NOT_FOUND;
411
412 if (get_mh_cur_folder(session) == src_folder)
413 get_data(session)->mh_cur_folder = NULL;
414
415 r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name);
416
417 return mhdriver_mh_error_to_mail_error(r);
418}
419
420static int mhdriver_select_folder(mailsession * session, char * mb)
421{
422 struct mailmh_folder * folder;
423 struct mailmh * mh;
424 int r;
425
426 mh = get_mh_session(session);
427 if (mh == NULL)
428 return MAIL_ERROR_BAD_STATE;
429
430 r = mailmh_folder_update(mh->mh_main);
431
432 folder = mailmh_folder_find(mh->mh_main, mb);
433 if (folder == NULL)
434 return MAIL_ERROR_FOLDER_NOT_FOUND;
435
436 get_data(session)->mh_cur_folder = folder;
437 r = mailmh_folder_update(folder);
438
439 return mhdriver_mh_error_to_mail_error(r);
440}
441
442static int mhdriver_status_folder(mailsession * session, char * mb,
443 uint32_t * result_messages, uint32_t * result_recent,
444 uint32_t * result_unseen)
445{
446 uint32_t count;
447 int r;
448
449 r = mhdriver_messages_number(session, mb, &count);
450 if (r != MAIL_NO_ERROR)
451 return r;
452
453 * result_messages = count;
454 * result_recent = count;
455 * result_unseen = count;
456
457 return MAIL_NO_ERROR;
458}
459
460static int mhdriver_messages_number(mailsession * session, char * mb,
461 uint32_t * result)
462{
463 struct mailmh_folder * folder;
464 uint32_t count;
465 struct mailmh * mh;
466 unsigned int i;
467
468 mh = get_mh_session(session);
469 if (mh == NULL)
470 return MAIL_ERROR_BAD_STATE;
471
472 if (mb != NULL) {
473 folder = mailmh_folder_find(mh->mh_main, mb);
474 if (folder == NULL)
475 return MAIL_ERROR_FOLDER_NOT_FOUND;
476 }
477 else {
478 folder = get_mh_cur_folder(session);
479 if (folder == NULL)
480 return MAIL_ERROR_BAD_STATE;
481 }
482
483 mailmh_folder_update(folder);
484 count = 0;
485 for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
486 struct mailmh_msg_info * msg_info;
487
488 msg_info = carray_get(folder->fl_msgs_tab, i);
489 if (msg_info != NULL)
490 count ++;
491 }
492
493 * result = count;
494
495 return MAIL_NO_ERROR;
496}
497
498
499static int get_list_folders(struct mailmh_folder * folder, clist ** result)
500{
501 unsigned int i;
502 clist * list;
503 char * new_filename;
504 int res;
505 int r;
506
507 list = * result;
508
509 new_filename = strdup(folder->fl_filename);
510 if (new_filename == NULL) {
511 res = MAIL_ERROR_MEMORY;
512 goto free;
513 }
514
515 r = mailmh_folder_update(folder);
516
517 switch (r) {
518 case MAILMH_NO_ERROR:
519 break;
520
521 default:
522 res = mhdriver_mh_error_to_mail_error(r);
523 goto free;
524 }
525
526 r = clist_append(list, new_filename);
527 if (r < 0) {
528 free(new_filename);
529 res = MAIL_ERROR_MEMORY;
530 goto free;
531 }
532
533 if (folder->fl_subfolders_tab != NULL) {
534 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
535 struct mailmh_folder * subfolder;
536
537 subfolder = carray_get(folder->fl_subfolders_tab, i);
538
539 r = get_list_folders(subfolder, &list);
540 if (r != MAIL_NO_ERROR) {
541 res = MAIL_ERROR_MEMORY;
542 goto free;
543 }
544 }
545 }
546
547 * result = list;
548
549 return MAIL_NO_ERROR;
550
551 free:
552 clist_foreach(list, (clist_func) free, NULL);
553 clist_free(list);
554 return res;
555}
556
557
558static int mhdriver_list_folders(mailsession * session, char * mb,
559 struct mail_list ** result)
560{
561 clist * list;
562 int r;
563 struct mailmh * mh;
564 struct mail_list * ml;
565
566 mh = get_mh_session(session);
567
568 if (mh == NULL)
569 return MAIL_ERROR_BAD_STATE;
570
571 list = clist_new();
572 if (list == NULL)
573 return MAIL_ERROR_MEMORY;
574
575 r = get_list_folders(mh->mh_main, &list);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 ml = mail_list_new(list);
580 if (ml == NULL)
581 goto free;
582
583 * result = ml;
584
585 return MAIL_NO_ERROR;
586
587 free:
588 clist_foreach(list, (clist_func) free, NULL);
589 clist_free(list);
590 return MAIL_ERROR_MEMORY;
591}
592
593static int mhdriver_lsub_folders(mailsession * session, char * mb,
594 struct mail_list ** result)
595{
596 clist * subscribed;
597 clist * lsub_result;
598 clistiter * cur;
599 struct mail_list * lsub;
600 size_t length;
601 int r;
602
603 length = strlen(mb);
604
605 subscribed = get_data(session)->mh_subscribed_list;
606
607 lsub_result = clist_new();
608 if (lsub_result == NULL)
609 return MAIL_ERROR_MEMORY;
610
611 for(cur = clist_begin(subscribed) ; cur != NULL ;
612 cur = clist_next(cur)) {
613 char * cur_mb;
614 char * new_mb;
615
616 cur_mb = clist_content(cur);
617
618 if (strncmp(mb, cur_mb, length) == 0) {
619 new_mb = strdup(cur_mb);
620 if (new_mb == NULL)
621 goto free_list;
622
623 r = clist_append(lsub_result, new_mb);
624 if (r < 0) {
625 free(new_mb);
626 goto free_list;
627 }
628 }
629 }
630
631 lsub = mail_list_new(lsub_result);
632 if (lsub == NULL)
633 goto free_list;
634
635 * result = lsub;
636
637 return MAIL_NO_ERROR;
638
639 free_list:
640 clist_foreach(lsub_result, (clist_func) free, NULL);
641 clist_free(lsub_result);
642 return MAIL_ERROR_MEMORY;
643}
644
645static int mhdriver_subscribe_folder(mailsession * session, char * mb)
646{
647 int r;
648
649 r = add_to_list(session, mb);
650 if (r < 0)
651 return MAIL_ERROR_SUBSCRIBE;
652
653 return MAIL_NO_ERROR;
654}
655
656static int mhdriver_unsubscribe_folder(mailsession * session, char * mb)
657{
658 int r;
659
660 r = remove_from_list(session, mb);
661 if (r < 0)
662 return MAIL_ERROR_UNSUBSCRIBE;
663
664 return MAIL_NO_ERROR;
665}
666
667/* messages operations */
668
669static int mhdriver_append_message(mailsession * session,
670 char * message, size_t size)
671{
672 int r;
673 struct mailmh_folder * folder;
674
675 folder = get_mh_cur_folder(session);
676 if (folder == NULL)
677 return MAIL_ERROR_BAD_STATE;
678
679 r = mailmh_folder_add_message(folder, message, size);
680
681 switch (r) {
682 case MAILMH_ERROR_FILE:
683 return MAIL_ERROR_DISKSPACE;
684
685 default:
686 return mhdriver_mh_error_to_mail_error(r);
687 }
688}
689
690static int mhdriver_append_message_flags(mailsession * session,
691 char * message, size_t size, struct mail_flags * flags)
692{
693 return mhdriver_append_message(session, message, size);
694}
695
696static int mhdriver_copy_message(mailsession * session,
697 uint32_t num, char * mb)
698{
699 int fd;
700 int r;
701 struct mailmh_folder * folder;
702 struct mailmh * mh;
703 int res;
704
705 mh = get_mh_session(session);
706 if (mh == NULL) {
707 res = MAIL_ERROR_BAD_STATE;
708 goto err;
709 }
710
711 folder = get_mh_cur_folder(session);
712 if (folder == NULL) {
713 res = MAIL_ERROR_BAD_STATE;
714 goto err;
715 }
716
717 r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd);
718 if (r != MAIL_NO_ERROR) {
719 res = r;
720 goto err;
721 }
722
723 folder = mailmh_folder_find(mh->mh_main, mb);
724 if (folder == NULL) {
725 res = MAIL_ERROR_FOLDER_NOT_FOUND;
726 goto close;
727 }
728
729 r = mailmh_folder_add_message_file(folder, fd);
730 if (r != MAIL_NO_ERROR) {
731 res = MAIL_ERROR_COPY;
732 goto close;
733 }
734
735 close(fd);
736
737 return MAIL_NO_ERROR;
738
739 close:
740 close(fd);
741 err:
742 return res;
743}
744
745static int mhdriver_remove_message(mailsession * session, uint32_t num)
746{
747 int r;
748 struct mailmh_folder * folder;
749
750 folder = get_mh_cur_folder(session);
751 if (folder == NULL)
752 return MAIL_ERROR_DELETE;
753
754 r = mailmh_folder_remove_message(folder, num);
755
756 return mhdriver_mh_error_to_mail_error(r);
757}
758
759static int mhdriver_move_message(mailsession * session,
760 uint32_t num, char * mb)
761{
762 int r;
763 struct mailmh_folder * src_folder;
764 struct mailmh_folder * dest_folder;
765 struct mailmh * mh;
766
767 mh = get_mh_session(session);
768 if (mh == NULL)
769 return MAIL_ERROR_BAD_STATE;
770
771 src_folder = get_mh_cur_folder(session);
772 if (src_folder == NULL)
773 return MAIL_ERROR_BAD_STATE;
774
775 dest_folder = mailmh_folder_find(mh->mh_main, mb);
776 if (dest_folder == NULL)
777 return MAIL_ERROR_FOLDER_NOT_FOUND;
778
779 r = mailmh_folder_move_message(dest_folder, src_folder, num);
780
781 return mhdriver_mh_error_to_mail_error(r);
782}
783
784
785static int mhdriver_get_messages_list(mailsession * session,
786 struct mailmessage_list ** result)
787{
788 struct mailmh_folder * folder;
789 int res;
790
791 folder = get_mh_cur_folder(session);
792 if (folder == NULL) {
793 res = MAIL_ERROR_BAD_STATE;
794 goto err;
795 }
796
797 mailmh_folder_update(folder);
798 return mh_get_messages_list(folder, session, mh_message_driver, result);
799
800 err:
801 return res;
802}
803
804static int mhdriver_get_message(mailsession * session,
805 uint32_t num, mailmessage ** result)
806{
807 mailmessage * msg_info;
808 int r;
809
810 msg_info = mailmessage_new();
811 if (msg_info == NULL)
812 return MAIL_ERROR_MEMORY;
813
814 r = mailmessage_init(msg_info, session, mh_message_driver, num, 0);
815 if (r != MAIL_NO_ERROR) {
816 mailmessage_free(msg_info);
817 return r;
818 }
819
820 * result = msg_info;
821
822 return MAIL_NO_ERROR;
823}
824
825static int mhdriver_get_message_by_uid(mailsession * session,
826 const char * uid,
827 mailmessage ** result)
828{
829 uint32_t index;
830 char *p;
831 struct mailmh_msg_info * mh_msg_info;
832 struct mh_session_state_data * mh_data;
833 chashdatum key;
834 chashdatum data;
835 int r;
836 time_t mtime;
837 char * mtime_p;
838
839 if (uid == NULL)
840 return MAIL_ERROR_INVAL;
841
842 index = strtoul(uid, &p, 10);
843 if (p == uid || * p != '-')
844 return MAIL_ERROR_INVAL;
845
846 mh_data = session->sess_data;
847#if 0
848 mh_msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, index);
849#endif
850 key.data = &index;
851 key.len = sizeof(index);
852 r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data);
853 if (r < 0)
854 return MAIL_ERROR_MSG_NOT_FOUND;
855
856 mh_msg_info = data.data;
857
858 mtime_p = p + 1;
859
860 mtime = strtoul(mtime_p, &p, 10);
861 if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
862 size_t size;
863 char *size_p;
864
865 size_p = p + 1;
866 size = strtoul(size_p, &p, 10);
867 if ((* p == '\0') && (size == mh_msg_info->msg_size))
868 return mhdriver_get_message(session, index, result);
869 }
870 else if (* p != '-') {
871 return MAIL_ERROR_INVAL;
872 }
873
874 return MAIL_ERROR_MSG_NOT_FOUND;
875}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver.h b/libetpan/src/driver/implementation/mh/mhdriver.h
new file mode 100644
index 0000000..a3f45f5
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_H
37
38#define MHDRIVER_H
39
40#include <libetpan/maildriver.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached.c b/libetpan/src/driver/implementation/mh/mhdriver_cached.c
new file mode 100644
index 0000000..1e5c28b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached.c
@@ -0,0 +1,1315 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_cached.h"
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <dirent.h>
41#include <unistd.h>
42#include <sys/stat.h>
43#include <ctype.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "mail.h"
50#include "mail_cache_db.h"
51
52#include "generic_cache.h"
53#include "imfcache.h"
54#include "mhdriver.h"
55
56#include "mhdriver_cached_message.h"
57#include "mailmh.h"
58#include "maildriver_tools.h"
59#include "mhdriver_tools.h"
60#include "mailmessage.h"
61
62static int mhdriver_cached_initialize(mailsession * session);
63
64static void mhdriver_cached_uninitialize(mailsession * session);
65
66static int mhdriver_cached_parameters(mailsession * session,
67 int id, void * value);
68
69static int mhdriver_cached_connect_path(mailsession * session, char * path);
70static int mhdriver_cached_logout(mailsession * session);
71
72static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
73 char * name, char ** result);
74static int mhdriver_cached_create_folder(mailsession * session, char * mb);
75
76static int mhdriver_cached_delete_folder(mailsession * session, char * mb);
77
78static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
79 char * new_name);
80
81static int mhdriver_cached_check_folder(mailsession * session);
82
83static int mhdriver_cached_select_folder(mailsession * session, char * mb);
84
85static int mhdriver_cached_expunge_folder(mailsession * session);
86
87static int mhdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages, uint32_t * result_recent,
89 uint32_t * result_unseen);
90
91static int mhdriver_cached_messages_number(mailsession * session, char * mb,
92 uint32_t * result);
93static int mhdriver_cached_recent_number(mailsession * session, char * mb,
94 uint32_t * result);
95static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
96 uint32_t * result);
97
98static int mhdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100
101static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
102 struct mail_list ** result);
103
104static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb);
105
106static int mhdriver_cached_unsubscribe_folder(mailsession * session,
107 char * mb);
108
109static int mhdriver_cached_append_message(mailsession * session,
110 char * message, size_t size);
111static int mhdriver_cached_append_message_flags(mailsession * session,
112 char * message, size_t size, struct mail_flags * flags);
113static int mhdriver_cached_copy_message(mailsession * session,
114 uint32_t num, char * mb);
115
116static int mhdriver_cached_remove_message(mailsession * session,
117 uint32_t num);
118
119static int mhdriver_cached_move_message(mailsession * session,
120 uint32_t num, char * mb);
121
122static int
123mhdriver_cached_get_messages_list(mailsession * session,
124 struct mailmessage_list ** result);
125
126static int
127mhdriver_cached_get_envelopes_list(mailsession * session,
128 struct mailmessage_list * env_list);
129
130static int mhdriver_cached_get_message(mailsession * session,
131 uint32_t num, mailmessage ** result);
132
133static int mhdriver_cached_get_message_by_uid(mailsession * session,
134 const char * uid,
135 mailmessage ** result);
136
137static mailsession_driver local_mh_cached_session_driver = {
138 .sess_name = "mh-cached",
139
140 .sess_initialize = mhdriver_cached_initialize,
141 .sess_uninitialize = mhdriver_cached_uninitialize,
142
143 .sess_parameters = mhdriver_cached_parameters,
144
145 .sess_connect_stream = NULL,
146 .sess_connect_path = mhdriver_cached_connect_path,
147 .sess_starttls = NULL,
148 .sess_login = NULL,
149 .sess_logout = mhdriver_cached_logout,
150 .sess_noop = NULL,
151
152 .sess_build_folder_name = mhdriver_cached_build_folder_name,
153 .sess_create_folder = mhdriver_cached_create_folder,
154 .sess_delete_folder = mhdriver_cached_delete_folder,
155 .sess_rename_folder = mhdriver_cached_rename_folder,
156 .sess_check_folder = mhdriver_cached_check_folder,
157 .sess_examine_folder = NULL,
158 .sess_select_folder = mhdriver_cached_select_folder,
159 .sess_expunge_folder = mhdriver_cached_expunge_folder,
160 .sess_status_folder = mhdriver_cached_status_folder,
161 .sess_messages_number = mhdriver_cached_messages_number,
162 .sess_recent_number = mhdriver_cached_recent_number,
163 .sess_unseen_number = mhdriver_cached_unseen_number,
164 .sess_list_folders = mhdriver_cached_list_folders,
165 .sess_lsub_folders = mhdriver_cached_lsub_folders,
166 .sess_subscribe_folder = mhdriver_cached_subscribe_folder,
167 .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder,
168
169 .sess_append_message = mhdriver_cached_append_message,
170 .sess_append_message_flags = mhdriver_cached_append_message_flags,
171 .sess_copy_message = mhdriver_cached_copy_message,
172 .sess_move_message = mhdriver_cached_move_message,
173
174 .sess_get_messages_list = mhdriver_cached_get_messages_list,
175 .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list,
176 .sess_remove_message = mhdriver_cached_remove_message,
177#if 0
178 .sess_search_messages = maildriver_generic_search_messages,
179#endif
180
181 .sess_get_message = mhdriver_cached_get_message,
182 .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid,
183};
184
185mailsession_driver * mh_cached_session_driver =
186&local_mh_cached_session_driver;
187
188#define ENV_NAME "env.db"
189#define FLAGS_NAME "flags.db"
190
191
192static inline struct mh_cached_session_state_data *
193get_cached_data(mailsession * session)
194{
195 return session->sess_data;
196}
197
198static inline mailsession * get_ancestor(mailsession * session)
199{
200 return get_cached_data(session)->mh_ancestor;
201}
202
203static inline struct mh_session_state_data *
204get_ancestor_data(mailsession * session)
205{
206 return get_ancestor(session)->sess_data;
207}
208
209static inline struct mailmh *
210get_mh_session(mailsession * session)
211{
212 return get_ancestor_data(session)->mh_session;
213}
214
215static inline struct mailmh_folder *
216get_mh_cur_folder(mailsession * session)
217{
218 return get_ancestor_data(session)->mh_cur_folder;
219}
220
221
222#define FILENAME_MAX_UID "max-uid"
223
224/* write max uid current value */
225
226static int write_max_uid_value(mailsession * session)
227{
228 int r;
229 char filename[PATH_MAX];
230 FILE * f;
231 int res;
232 struct mh_cached_session_state_data * cached_data;
233 struct mh_session_state_data * ancestor_data;
234 int fd;
235
236 MMAPString * mmapstr;
237 size_t cur_token;
238
239 cached_data = get_cached_data(session);
240 ancestor_data = get_ancestor_data(session);
241
242 if (cached_data->mh_quoted_mb == NULL)
243 return MAIL_ERROR_BAD_STATE;
244
245 snprintf(filename, PATH_MAX, "%s/%s/%s",
246 cached_data->mh_cache_directory,
247 cached_data->mh_quoted_mb, FILENAME_MAX_UID);
248
249 fd = creat(filename, S_IRUSR | S_IWUSR);
250 if (fd < 0) {
251 res = MAIL_ERROR_FILE;
252 goto err;
253 }
254
255 f = fdopen(fd, "w");
256 if (f == NULL) {
257 close(fd);
258 res = MAIL_ERROR_FILE;
259 goto err;
260 }
261
262 mmapstr = mmap_string_new("");
263 if (mmapstr == NULL) {
264 res = MAIL_ERROR_MEMORY;
265 goto close;
266 }
267
268 r = mail_serialize_clear(mmapstr, &cur_token);
269 if (r != MAIL_NO_ERROR) {
270 res = r;
271 goto free_mmapstr;
272 }
273
274 r = mailimf_cache_int_write(mmapstr, &cur_token,
275 ancestor_data->mh_cur_folder->fl_max_index);
276 if (r != MAIL_NO_ERROR) {
277 res = r;
278 goto free_mmapstr;
279 }
280
281 fwrite(mmapstr->str, 1, mmapstr->len, f);
282
283 mmap_string_free(mmapstr);
284 fclose(f);
285
286 return MAIL_NO_ERROR;
287
288 free_mmapstr:
289 mmap_string_free(mmapstr);
290 close:
291 fclose(f);
292 err:
293 return res;
294}
295
296static int read_max_uid_value(mailsession * session)
297{
298 int r;
299 char filename[PATH_MAX];
300 FILE * f;
301 uint32_t written_uid;
302 int res;
303 struct mh_cached_session_state_data * cached_data;
304 struct mh_session_state_data * ancestor_data;
305
306 MMAPString * mmapstr;
307 size_t cur_token;
308 char buf[sizeof(uint32_t)];
309 size_t read_size;
310
311 cached_data = get_cached_data(session);
312 ancestor_data = get_ancestor_data(session);
313
314 snprintf(filename, PATH_MAX, "%s/%s/%s",
315 cached_data->mh_cache_directory,
316 cached_data->mh_quoted_mb, FILENAME_MAX_UID);
317
318 f = fopen(filename, "r");
319 if (f == NULL) {
320 res = MAIL_ERROR_FILE;
321 goto err;
322 }
323
324 read_size = fread(buf, 1, sizeof(uint32_t), f);
325
326 mmapstr = mmap_string_new_len(buf, read_size);
327 if (mmapstr == NULL) {
328 res = MAIL_ERROR_MEMORY;
329 goto close;
330 }
331
332 cur_token = 0;
333
334 r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid);
335 if (r != MAIL_NO_ERROR) {
336 fclose(f);
337 res = r;
338 goto free_mmapstr;
339 }
340
341 mmap_string_free(mmapstr);
342 fclose(f);
343
344 if (written_uid > ancestor_data->mh_cur_folder->fl_max_index)
345 ancestor_data->mh_cur_folder->fl_max_index = written_uid;
346
347 return MAIL_NO_ERROR;
348
349 free_mmapstr:
350 mmap_string_free(mmapstr);
351 close:
352 fclose(f);
353 err:
354 return res;
355}
356
357
358static int mhdriver_cached_initialize(mailsession * session)
359{
360 struct mh_cached_session_state_data * data;
361
362 data = malloc(sizeof(* data));
363 if (data == NULL)
364 goto err;
365
366 data->mh_flags_store = mail_flags_store_new();
367 if (data->mh_flags_store == NULL)
368 goto free;
369
370 data->mh_ancestor = mailsession_new(mh_session_driver);
371 if (data->mh_ancestor == NULL)
372 goto free_store;
373
374 data->mh_quoted_mb = NULL;
375
376 session->sess_data = data;
377
378 return MAIL_NO_ERROR;
379
380 free_store:
381 mail_flags_store_free(data->mh_flags_store);
382 free:
383 free(data);
384 err:
385 return MAIL_ERROR_MEMORY;
386}
387
388static void free_state(struct mh_cached_session_state_data * mh_data)
389{
390 if (mh_data->mh_quoted_mb) {
391 free(mh_data->mh_quoted_mb);
392 mh_data->mh_quoted_mb = NULL;
393 }
394}
395
396static int mh_flags_store_process(char * flags_directory, char * quoted_mb,
397 struct mail_flags_store * flags_store)
398{
399 char filename_flags[PATH_MAX];
400 struct mail_cache_db * cache_db_flags;
401 MMAPString * mmapstr;
402 unsigned int i;
403 int r;
404 int res;
405
406 if (carray_count(flags_store->fls_tab) == 0)
407 return MAIL_NO_ERROR;
408
409 if (quoted_mb == NULL)
410 return MAIL_NO_ERROR;
411
412 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
413 flags_directory, quoted_mb, FLAGS_NAME);
414
415 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
416 if (r < 0) {
417 res = MAIL_ERROR_FILE;
418 goto err;
419 }
420
421 mmapstr = mmap_string_new("");
422 if (mmapstr == NULL) {
423 res = MAIL_ERROR_MEMORY;
424 goto close_db_flags;
425 }
426
427 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
428 mailmessage * msg;
429
430 msg = carray_get(flags_store->fls_tab, i);
431
432 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
433 msg->msg_uid, msg->msg_flags);
434 }
435
436 mmap_string_free(mmapstr);
437 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
438
439 mail_flags_store_clear(flags_store);
440
441 return MAIL_NO_ERROR;
442
443 close_db_flags:
444 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
445 err:
446 return res;
447}
448
449static void mhdriver_cached_uninitialize(mailsession * session)
450{
451 struct mh_cached_session_state_data * data;
452
453 data = get_cached_data(session);
454
455 mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb,
456 data->mh_flags_store);
457
458 mail_flags_store_free(data->mh_flags_store);
459
460 free_state(data);
461 mailsession_free(data->mh_ancestor);
462 free(data);
463
464 session->sess_data = NULL;
465}
466
467static int mhdriver_cached_parameters(mailsession * session,
468 int id, void * value)
469{
470 struct mh_cached_session_state_data * cached_data;
471 int r;
472
473 cached_data = get_cached_data(session);
474
475 switch (id) {
476 case MHDRIVER_CACHED_SET_CACHE_DIRECTORY:
477 strncpy(cached_data->mh_cache_directory, value, PATH_MAX);
478 cached_data->mh_cache_directory[PATH_MAX - 1] = '\0';
479
480 r = generic_cache_create_dir(cached_data->mh_cache_directory);
481 if (r != MAIL_NO_ERROR)
482 return r;
483
484 return MAIL_NO_ERROR;
485
486 case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY:
487 strncpy(cached_data->mh_flags_directory, value, PATH_MAX);
488 cached_data->mh_flags_directory[PATH_MAX - 1] = '\0';
489
490 r = generic_cache_create_dir(cached_data->mh_flags_directory);
491 if (r != MAIL_NO_ERROR)
492 return r;
493
494 return MAIL_NO_ERROR;
495 }
496
497 return MAIL_ERROR_INVAL;
498}
499
500static int mhdriver_cached_connect_path(mailsession * session, char * path)
501{
502 return mailsession_connect_path(get_ancestor(session), path);
503}
504
505static int mhdriver_cached_logout(mailsession * session)
506{
507 int r;
508 struct mh_cached_session_state_data * cached_data;
509
510 r = write_max_uid_value(session);
511
512 cached_data = get_cached_data(session);
513
514 mh_flags_store_process(cached_data->mh_flags_directory,
515 cached_data->mh_quoted_mb,
516 cached_data->mh_flags_store);
517
518 return mailsession_logout(get_ancestor(session));
519}
520
521static int mhdriver_cached_check_folder(mailsession * session)
522{
523 struct mh_cached_session_state_data * cached_data;
524
525 cached_data = get_cached_data(session);
526
527 mh_flags_store_process(cached_data->mh_flags_directory,
528 cached_data->mh_quoted_mb,
529 cached_data->mh_flags_store);
530
531 return MAIL_NO_ERROR;
532}
533
534/* folders operations */
535
536static int mhdriver_cached_build_folder_name(mailsession * session, char * mb,
537 char * name, char ** result)
538{
539 return mailsession_build_folder_name(get_ancestor(session),
540 mb, name, result);
541}
542
543static int mhdriver_cached_create_folder(mailsession * session, char * mb)
544{
545 return mailsession_create_folder(get_ancestor(session), mb);
546}
547
548static int mhdriver_cached_delete_folder(mailsession * session, char * mb)
549{
550 return mailsession_delete_folder(get_ancestor(session), mb);
551}
552
553static int mhdriver_cached_rename_folder(mailsession * session, char * mb,
554 char * new_name)
555{
556 return mailsession_rename_folder(get_ancestor(session), mb, new_name);
557}
558
559static int get_cache_directory(mailsession * session,
560 char * path, char ** result)
561{
562 char * quoted_mb;
563 char dirname[PATH_MAX];
564 int res;
565 int r;
566 struct mh_cached_session_state_data * cached_data;
567
568 cached_data = get_cached_data(session);
569
570 quoted_mb = maildriver_quote_mailbox(path);
571 if (quoted_mb == NULL) {
572 res = MAIL_ERROR_MEMORY;
573 goto err;
574 }
575
576 snprintf(dirname, PATH_MAX, "%s/%s",
577 cached_data->mh_cache_directory, quoted_mb);
578
579 r = generic_cache_create_dir(dirname);
580 if (r != MAIL_NO_ERROR) {
581 res = r;
582 goto free;
583 }
584
585 snprintf(dirname, PATH_MAX, "%s/%s",
586 cached_data->mh_flags_directory, quoted_mb);
587
588 r = generic_cache_create_dir(dirname);
589 if (r != MAIL_NO_ERROR) {
590 res = r;
591 goto free;
592 }
593
594 * result = quoted_mb;
595
596 return MAIL_NO_ERROR;
597
598 free:
599 free(quoted_mb);
600 err:
601 return res;
602}
603
604static int mhdriver_cached_select_folder(mailsession * session, char * mb)
605{
606 int r;
607 int res;
608 char * quoted_mb;
609 struct mh_cached_session_state_data * cached_data;
610
611 cached_data = get_cached_data(session);
612
613 mh_flags_store_process(cached_data->mh_flags_directory,
614 cached_data->mh_quoted_mb,
615 cached_data->mh_flags_store);
616
617 r = get_cache_directory(session, mb, &quoted_mb);
618 if (r != MAIL_NO_ERROR) {
619 res = r;
620 goto err;
621 }
622
623 r = mailsession_select_folder(get_ancestor(session), mb);
624 if (r != MAIL_NO_ERROR) {
625 res = r;
626 goto free;
627 }
628
629 r = write_max_uid_value(session);
630
631 free_state(cached_data);
632 cached_data->mh_quoted_mb = quoted_mb;
633
634 r = read_max_uid_value(session);
635
636 return MAIL_NO_ERROR;
637
638 free:
639 free(quoted_mb);
640 err:
641 return res;
642}
643
644static int mhdriver_cached_expunge_folder(mailsession * session)
645{
646 struct mailmh_folder * folder;
647 int res;
648 char filename_flags[PATH_MAX];
649 struct mail_cache_db * cache_db_flags;
650 MMAPString * mmapstr;
651 struct mh_cached_session_state_data * cached_data;
652 unsigned int i;
653 int r;
654
655 cached_data = get_cached_data(session);
656 if (cached_data->mh_quoted_mb == NULL) {
657 res = MAIL_ERROR_BAD_STATE;
658 goto err;
659 }
660
661 mh_flags_store_process(cached_data->mh_flags_directory,
662 cached_data->mh_quoted_mb,
663 cached_data->mh_flags_store);
664
665 folder = get_mh_cur_folder(session);
666 if (folder == NULL) {
667 res = MAIL_ERROR_BAD_STATE;
668 goto err;
669 }
670
671 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
672 cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
673
674 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
675 if (r < 0) {
676 res = MAIL_ERROR_FILE;
677 goto err;
678 }
679
680 mmapstr = mmap_string_new("");
681 if (mmapstr == NULL) {
682 res = MAIL_ERROR_MEMORY;
683 goto close_db_flags;
684 }
685
686 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
687 struct mailmh_msg_info * mh_info;
688 struct mail_flags * flags;
689
690 mh_info = carray_get(folder->fl_msgs_tab, i);
691 if (mh_info == NULL)
692 continue;
693
694 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
695 session, mh_info->msg_index, &flags);
696 if (r != MAIL_NO_ERROR)
697 continue;
698
699 if (flags->fl_flags & MAIL_FLAG_DELETED) {
700 r = mailmh_folder_remove_message(folder, mh_info->msg_index);
701 }
702
703 mail_flags_free(flags);
704 }
705
706 mmap_string_free(mmapstr);
707 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
708
709 mailmh_folder_update(folder);
710
711 return MAIL_NO_ERROR;
712
713 close_db_flags:
714 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
715 err:
716 return res;
717}
718
719
720static int mhdriver_cached_status_folder(mailsession * session, char * mb,
721 uint32_t * result_messages,
722 uint32_t * result_recent,
723 uint32_t * result_unseen)
724{
725 struct mailmh_folder * folder;
726 int res;
727 char filename_flags[PATH_MAX];
728 struct mail_cache_db * cache_db_flags;
729 MMAPString * mmapstr;
730 struct mh_cached_session_state_data * cached_data;
731 unsigned int i;
732 int r;
733 uint32_t count;
734 uint32_t recent;
735 uint32_t unseen;
736
737 r = mhdriver_cached_select_folder(session, mb);
738 if (r != MAIL_NO_ERROR) {
739 res = r;
740 goto err;
741 }
742
743 count = 0;
744 recent = 0;
745 unseen = 0;
746
747 folder = get_mh_cur_folder(session);
748 if (folder == NULL) {
749 res = MAIL_ERROR_BAD_STATE;
750 goto err;
751 }
752
753 cached_data = get_cached_data(session);
754 if (cached_data->mh_quoted_mb == NULL) {
755 res = MAIL_ERROR_BAD_STATE;
756 goto err;
757 }
758
759 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
760 cached_data->mh_flags_directory,
761 cached_data->mh_quoted_mb, FLAGS_NAME);
762
763 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
764 if (r < 0) {
765 res = MAIL_ERROR_FILE;
766 goto err;
767 }
768
769 mmapstr = mmap_string_new("");
770 if (mmapstr == NULL) {
771 res = MAIL_ERROR_MEMORY;
772 goto close_db_flags;
773 }
774
775 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
776 struct mailmh_msg_info * mh_info;
777 struct mail_flags * flags;
778
779 mh_info = carray_get(folder->fl_msgs_tab, i);
780 if (mh_info == NULL)
781 continue;
782
783 count ++;
784
785 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
786 session, mh_info->msg_index,
787 &flags);
788
789 if (r != MAIL_NO_ERROR) {
790 recent ++;
791 unseen ++;
792 continue;
793 }
794
795 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
796 recent ++;
797 }
798 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
799 unseen ++;
800 }
801 mail_flags_free(flags);
802 }
803
804 mmap_string_free(mmapstr);
805 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
806
807 * result_messages = count;
808 * result_recent = recent;
809 * result_unseen = unseen;
810
811 return MAIL_NO_ERROR;
812
813 close_db_flags:
814 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
815 err:
816 return res;
817}
818
819static int mhdriver_cached_messages_number(mailsession * session, char * mb,
820 uint32_t * result)
821{
822 return mailsession_messages_number(get_ancestor(session), mb, result);
823}
824
825static int mhdriver_cached_recent_number(mailsession * session, char * mb,
826 uint32_t * result)
827{
828 uint32_t messages;
829 uint32_t recent;
830 uint32_t unseen;
831 int r;
832
833 r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
834 if (r != MAIL_NO_ERROR)
835 return r;
836
837 * result = recent;
838
839 return MAIL_NO_ERROR;
840}
841
842
843static int mhdriver_cached_unseen_number(mailsession * session, char * mb,
844 uint32_t * result)
845{
846 uint32_t messages;
847 uint32_t recent;
848 uint32_t unseen;
849 int r;
850
851 r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen);
852 if (r != MAIL_NO_ERROR)
853 return r;
854
855 * result = recent;
856
857 return MAIL_NO_ERROR;
858}
859
860
861static int mhdriver_cached_list_folders(mailsession * session, char * mb,
862 struct mail_list ** result)
863{
864 return mailsession_list_folders(get_ancestor(session), mb, result);
865}
866
867static int mhdriver_cached_lsub_folders(mailsession * session, char * mb,
868 struct mail_list ** result)
869{
870 return mailsession_lsub_folders(get_ancestor(session), mb, result);
871}
872
873static int mhdriver_cached_subscribe_folder(mailsession * session, char * mb)
874{
875 return mailsession_subscribe_folder(get_ancestor(session), mb);
876}
877
878static int mhdriver_cached_unsubscribe_folder(mailsession * session,
879 char * mb)
880{
881 return mailsession_unsubscribe_folder(get_ancestor(session), mb);
882}
883
884/* messages operations */
885
886static int mhdriver_cached_append_message(mailsession * session,
887 char * message, size_t size)
888{
889 return mhdriver_cached_append_message_flags(session,
890 message, size, NULL);
891}
892
893static int mhdriver_cached_append_message_flags(mailsession * session,
894 char * message, size_t size, struct mail_flags * flags)
895{
896 int r;
897 struct mailmh_folder * folder;
898 struct mailmh_msg_info * msg_info;
899 chashdatum key;
900 chashdatum value;
901 uint32_t uid;
902 struct mh_cached_session_state_data * data;
903 char filename_flags[PATH_MAX];
904 struct mail_cache_db * cache_db_flags;
905 MMAPString * mmapstr;
906 char keyname[PATH_MAX];
907
908 folder = get_mh_cur_folder(session);
909 if (folder == NULL)
910 return MAIL_ERROR_BAD_STATE;
911
912 r = mailmh_folder_add_message_uid(folder,
913 message, size, &uid);
914
915 switch (r) {
916 case MAILMH_ERROR_FILE:
917 return MAIL_ERROR_DISKSPACE;
918
919 case MAILMH_NO_ERROR:
920 break;
921
922 default:
923 return mhdriver_mh_error_to_mail_error(r);
924 }
925
926 if (flags == NULL)
927 goto exit;
928
929 key.data = &uid;
930 key.len = sizeof(uid);
931 r = chash_get(folder->fl_msgs_hash, &key, &value);
932 if (r < 0)
933 return MAIL_ERROR_CACHE_MISS;
934
935 msg_info = value.data;
936
937 data = get_cached_data(session);
938
939 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
940 data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME);
941
942 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
943 if (r < 0)
944 goto exit;
945
946 mmapstr = mmap_string_new("");
947 if (mmapstr == NULL)
948 goto close_db_flags;
949
950 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
951 uid, (unsigned long) msg_info->msg_mtime,
952 (unsigned long) msg_info->msg_size);
953
954 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags);
955
956 mmap_string_free(mmapstr);
957 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
958
959 if (r != MAIL_NO_ERROR)
960 goto exit;
961
962 return MAIL_NO_ERROR;
963
964 close_db_flags:
965 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
966 exit:
967 return MAIL_NO_ERROR;
968}
969
970static int mhdriver_cached_copy_message(mailsession * session,
971 uint32_t num, char * mb)
972{
973 return mailsession_copy_message(get_ancestor(session), num, mb);
974}
975
976static int mhdriver_cached_remove_message(mailsession * session, uint32_t num)
977{
978 return mailsession_remove_message(get_ancestor(session), num);
979}
980
981static int mhdriver_cached_move_message(mailsession * session,
982 uint32_t num, char * mb)
983{
984 return mailsession_move_message(get_ancestor(session), num, mb);
985}
986
987static int
988mhdriver_cached_get_messages_list(mailsession * session,
989 struct mailmessage_list ** result)
990{
991 struct mailmh_folder * folder;
992 int res;
993
994 folder = get_mh_cur_folder(session);
995 if (folder == NULL) {
996 res = MAIL_ERROR_BAD_STATE;
997 goto err;
998 }
999
1000 return mh_get_messages_list(folder, session,
1001 mh_cached_message_driver, result);
1002
1003 err:
1004 return res;
1005}
1006
1007
1008
1009static int
1010get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1011 mailsession * session, uint32_t num,
1012 struct mailimf_fields ** result)
1013{
1014 int r;
1015 char keyname[PATH_MAX];
1016 struct mailimf_fields * fields;
1017 int res;
1018 struct mailmh_folder * folder;
1019 struct mailmh_msg_info * msg_info;
1020 chashdatum key;
1021 chashdatum data;
1022
1023 folder = get_mh_cur_folder(session);
1024
1025#if 0
1026 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
1027 if (msg_info == NULL)
1028 return MAIL_ERROR_CACHE_MISS;
1029#endif
1030 key.data = &num;
1031 key.len = sizeof(num);
1032 r = chash_get(folder->fl_msgs_hash, &key, &data);
1033 if (r < 0)
1034 return MAIL_ERROR_CACHE_MISS;
1035 msg_info = data.data;
1036
1037 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
1038 num, (unsigned long) msg_info->msg_mtime,
1039 (unsigned long) msg_info->msg_size);
1040
1041 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
1042 if (r != MAIL_NO_ERROR) {
1043 res = r;
1044 goto err;
1045 }
1046
1047 * result = fields;
1048
1049 return MAIL_NO_ERROR;
1050
1051 err:
1052 return res;
1053}
1054
1055static int
1056write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
1057 mailsession * session, uint32_t num,
1058 struct mailimf_fields * fields)
1059{
1060 int r;
1061 char keyname[PATH_MAX];
1062 int res;
1063 struct mailmh_folder * folder;
1064 chashdatum key;
1065 chashdatum data;
1066 struct mailmh_msg_info * msg_info;
1067
1068 folder = get_mh_cur_folder(session);
1069#if 0
1070 msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num);
1071 if (msg_info == NULL) {
1072 res = MAIL_ERROR_CACHE_MISS;
1073 goto err;
1074 }
1075#endif
1076 key.data = &num;
1077 key.len = sizeof(num);
1078 r = chash_get(folder->fl_msgs_hash, &key, &data);
1079 if (r < 0)
1080 return MAIL_ERROR_CACHE_MISS;
1081 msg_info = data.data;
1082
1083 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope",
1084 num, (unsigned long) msg_info->msg_mtime,
1085 (unsigned long) msg_info->msg_size);
1086
1087 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
1088 if (r != MAIL_NO_ERROR) {
1089 res = r;
1090 goto err;
1091 }
1092
1093 return MAIL_NO_ERROR;
1094
1095 err:
1096 return res;
1097}
1098
1099static int
1100mhdriver_cached_get_envelopes_list(mailsession * session,
1101 struct mailmessage_list * env_list)
1102{
1103 int r;
1104 unsigned int i;
1105 char filename_env[PATH_MAX];
1106 char filename_flags[PATH_MAX];
1107 struct mail_cache_db * cache_db_env;
1108 struct mail_cache_db * cache_db_flags;
1109 MMAPString * mmapstr;
1110 int res;
1111 struct mh_cached_session_state_data * cached_data;
1112
1113 cached_data = get_cached_data(session);
1114 if (cached_data->mh_quoted_mb == NULL) {
1115 res = MAIL_ERROR_BAD_STATE;
1116 goto err;
1117 }
1118
1119 mh_flags_store_process(cached_data->mh_flags_directory,
1120 cached_data->mh_quoted_mb,
1121 cached_data->mh_flags_store);
1122
1123 mmapstr = mmap_string_new("");
1124 if (mmapstr == NULL) {
1125 res = MAIL_ERROR_MEMORY;
1126 goto err;
1127 }
1128
1129 snprintf(filename_env, PATH_MAX, "%s/%s/%s",
1130 cached_data->mh_cache_directory,
1131 cached_data->mh_quoted_mb, ENV_NAME);
1132
1133 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1134 if (r < 0) {
1135 res = MAIL_ERROR_MEMORY;
1136 goto free_mmapstr;
1137 }
1138
1139 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
1140 cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME);
1141
1142 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1143 if (r < 0) {
1144 res = MAIL_ERROR_MEMORY;
1145 goto close_db_env;
1146 }
1147
1148 /* fill with cached */
1149
1150 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1151 mailmessage * msg;
1152 struct mailimf_fields * fields;
1153 struct mail_flags * flags;
1154
1155 msg = carray_get(env_list->msg_tab, i);
1156
1157 if (msg->msg_fields == NULL) {
1158 r = get_cached_envelope(cache_db_env, mmapstr,
1159 msg->msg_session, msg->msg_index, &fields);
1160 if (r == MAIL_NO_ERROR) {
1161 msg->msg_cached = TRUE;
1162 msg->msg_fields = fields;
1163 }
1164 }
1165
1166 if (msg->msg_flags == NULL) {
1167 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
1168 session, msg->msg_index, &flags);
1169 if (r == MAIL_NO_ERROR) {
1170 msg->msg_flags = flags;
1171 }
1172 }
1173 }
1174
1175 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1176 mail_cache_db_close_unlock(filename_env, cache_db_env);
1177
1178 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1179
1180 if (r != MAIL_NO_ERROR) {
1181 res = r;
1182 goto free_mmapstr;
1183 }
1184
1185 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
1186 if (r < 0) {
1187 res = MAIL_ERROR_MEMORY;
1188 goto free_mmapstr;
1189 }
1190
1191 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
1192 if (r < 0) {
1193 res = MAIL_ERROR_MEMORY;
1194 goto close_db_env;
1195 }
1196
1197 /* add flags */
1198
1199 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1200 mailmessage * msg;
1201
1202 msg = carray_get(env_list->msg_tab, i);
1203
1204 if (msg->msg_flags == NULL)
1205 msg->msg_flags = mail_flags_new_empty();
1206 }
1207
1208 /* must write cache */
1209
1210 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1211 mailmessage * msg;
1212
1213 msg = carray_get(env_list->msg_tab, i);
1214
1215 if (msg->msg_fields != NULL) {
1216 if (!msg->msg_cached) {
1217 r = write_cached_envelope(cache_db_env, mmapstr,
1218 session, msg->msg_index, msg->msg_fields);
1219 }
1220 }
1221
1222 if (msg->msg_flags != NULL) {
1223 r = mhdriver_write_cached_flags(cache_db_flags, mmapstr,
1224 msg->msg_uid, msg->msg_flags);
1225 }
1226 }
1227
1228 /* flush cache */
1229
1230 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
1231
1232 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
1233 mail_cache_db_close_unlock(filename_env, cache_db_env);
1234
1235 mmap_string_free(mmapstr);
1236
1237 return MAIL_NO_ERROR;
1238
1239 close_db_env:
1240 mail_cache_db_close_unlock(filename_env, cache_db_env);
1241 free_mmapstr:
1242 mmap_string_free(mmapstr);
1243 err:
1244 return res;
1245}
1246
1247static int mhdriver_cached_get_message(mailsession * session,
1248 uint32_t num, mailmessage ** result)
1249{
1250 mailmessage * msg_info;
1251 int r;
1252
1253 msg_info = mailmessage_new();
1254 if (msg_info == NULL)
1255 return MAIL_ERROR_MEMORY;
1256
1257 r = mailmessage_init(msg_info, session, mh_cached_message_driver, num, 0);
1258 if (r != MAIL_NO_ERROR)
1259 return r;
1260
1261 * result = msg_info;
1262
1263 return MAIL_NO_ERROR;
1264}
1265
1266static int mhdriver_cached_get_message_by_uid(mailsession * session,
1267 const char * uid,
1268 mailmessage ** result)
1269{
1270 uint32_t index;
1271 char *p;
1272 struct mailmh_msg_info * mh_msg_info;
1273 struct mailmh_folder * folder;
1274 time_t mtime;
1275 char * mtime_p;
1276 chashdatum key;
1277 chashdatum data;
1278 int r;
1279
1280 if (uid == NULL)
1281 return MAIL_ERROR_INVAL;
1282
1283 index = strtoul(uid, &p, 10);
1284 if (p == uid || * p != '-')
1285 return MAIL_ERROR_INVAL;
1286
1287 folder = get_mh_cur_folder(session);
1288
1289 mh_msg_info = NULL;
1290 key.data = &index;
1291 key.len = sizeof(index);
1292 r = chash_get(folder->fl_msgs_hash, &key, &data);
1293 if (r < 0)
1294 return MAIL_ERROR_MSG_NOT_FOUND;
1295
1296 mh_msg_info = data.data;
1297
1298 mtime_p = p + 1;
1299
1300 mtime = strtoul(mtime_p, &p, 10);
1301 if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) {
1302 size_t size;
1303 char *size_p;
1304
1305 size_p = p + 1;
1306 size = strtoul(size_p, &p, 10);
1307 if ((* p == '\0') && (size == mh_msg_info->msg_size))
1308 return mhdriver_cached_get_message(session, index, result);
1309 }
1310 else if (*p != '-') {
1311 return MAIL_ERROR_INVAL;
1312 }
1313
1314 return MAIL_ERROR_MSG_NOT_FOUND;
1315}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached.h b/libetpan/src/driver/implementation/mh/mhdriver_cached.h
new file mode 100644
index 0000000..d2e5803
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_H
37
38#define MHDRIVER_CACHED_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * mh_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c
new file mode 100644
index 0000000..a59beea
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c
@@ -0,0 +1,338 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mhdriver_tools.h"
40#include "mhdriver_cached.h"
41#include "mailmh.h"
42#include "generic_cache.h"
43
44#include "mail_cache_db.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mh_prefetch(mailmessage * msg_info);
55
56static void mh_prefetch_free(struct generic_message_t * msg);
57
58static int mh_initialize(mailmessage * msg_info);
59
60static int mh_fetch_size(mailmessage * msg_info,
61 size_t * result);
62
63static int mh_get_flags(mailmessage * msg_info,
64 struct mail_flags ** result);
65
66static void mh_uninitialize(mailmessage * msg_info);
67
68static void mh_flush(mailmessage * msg_info);
69
70static void mh_check(mailmessage * msg_info);
71
72static int mh_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mh_cached_message_driver = {
77 .msg_name = "mh-cached",
78
79 .msg_initialize = mh_initialize,
80 .msg_uninitialize = mh_uninitialize,
81
82 .msg_flush = mh_flush,
83 .msg_check = mh_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mh_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mh_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mh_get_flags,
99};
100
101mailmessage_driver * mh_cached_message_driver =
102&local_mh_cached_message_driver;
103
104static inline struct mh_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mh_ancestor;
113}
114
115static inline struct mh_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmh *
122get_mh_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mh_session;
125}
126
127static inline struct mailmh_folder *
128get_mh_cur_folder(mailmessage * msg)
129{
130 return get_ancestor_session_data(msg)->mh_cur_folder;
131}
132
133static int mh_prefetch(mailmessage * msg_info)
134{
135 struct generic_message_t * msg;
136 int r;
137 char * msg_content;
138 size_t msg_length;
139
140 r = mhdriver_fetch_message(get_ancestor_session(msg_info),
141 msg_info->msg_index, &msg_content, &msg_length);
142 if (r != MAIL_NO_ERROR)
143 return r;
144
145 msg = msg_info->msg_data;
146
147 msg->msg_message = msg_content;
148 msg->msg_length = msg_length;
149
150 return MAIL_NO_ERROR;
151}
152
153static void mh_prefetch_free(struct generic_message_t * msg)
154{
155 if (msg->msg_message != NULL) {
156 mmap_string_unref(msg->msg_message);
157 msg->msg_message = NULL;
158 }
159}
160
161static int mh_initialize(mailmessage * msg_info)
162{
163 struct generic_message_t * msg;
164 int r;
165 char * uid;
166 char static_uid[PATH_MAX];
167 struct mailmh_msg_info * mh_msg_info;
168 chashdatum key;
169 chashdatum data;
170 struct mailmh_folder * folder;
171
172 folder = get_mh_cur_folder(msg_info);
173
174 key.data = &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176 r = chash_get(folder->fl_msgs_hash, &key, &data);
177 if (r < 0)
178 return MAIL_ERROR_INVAL;
179
180 mh_msg_info = data.data;
181
182 snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
183 mh_msg_info->msg_mtime, (unsigned long) mh_msg_info->msg_size);
184 uid = strdup(static_uid);
185 if (uid == NULL)
186 return MAIL_ERROR_MEMORY;
187
188 r = mailmessage_generic_initialize(msg_info);
189 if (r != MAIL_NO_ERROR) {
190 free(uid);
191 return r;
192 }
193
194 msg = msg_info->msg_data;
195 msg->msg_prefetch = mh_prefetch;
196 msg->msg_prefetch_free = mh_prefetch_free;
197 msg_info->msg_uid = uid;
198
199 return MAIL_NO_ERROR;
200}
201
202static void mh_uninitialize(mailmessage * msg_info)
203{
204 mailmessage_generic_uninitialize(msg_info);
205}
206
207
208#define FLAGS_NAME "flags.db"
209
210static void mh_flush(mailmessage * msg_info)
211{
212 mailmessage_generic_flush(msg_info);
213}
214
215static void mh_check(mailmessage * msg_info)
216{
217 int r;
218
219 if (msg_info->msg_flags != NULL) {
220 r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store,
221 msg_info);
222 /* ignore errors */
223 }
224}
225
226static int mh_fetch_size(mailmessage * msg_info,
227 size_t * result)
228{
229 int r;
230 size_t size;
231
232 r = mhdriver_fetch_size(get_ancestor_session(msg_info),
233 msg_info->msg_index, &size);
234 if (r != MAIL_NO_ERROR)
235 return r;
236
237 * result = size;
238
239 return MAIL_NO_ERROR;
240}
241
242static int mh_get_flags(mailmessage * msg_info,
243 struct mail_flags ** result)
244{
245 int r;
246 struct mail_flags * flags;
247 struct mail_cache_db * cache_db_flags;
248 char filename_flags[PATH_MAX];
249 int res;
250 struct mh_cached_session_state_data * cached_data;
251 MMAPString * mmapstr;
252
253 if (msg_info->msg_flags != NULL) {
254 * result = msg_info->msg_flags;
255
256 return MAIL_NO_ERROR;
257 }
258
259 cached_data = get_cached_session_data(msg_info);
260
261 flags = mail_flags_store_get(cached_data->mh_flags_store,
262 msg_info->msg_index);
263
264 if (flags == NULL) {
265 if (cached_data->mh_quoted_mb == NULL) {
266 res = MAIL_ERROR_BAD_STATE;
267 goto err;
268 }
269
270 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
271 cached_data->mh_flags_directory,
272 cached_data->mh_quoted_mb, FLAGS_NAME);
273
274 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
275 if (r < 0) {
276 res = MAIL_ERROR_MEMORY;
277 goto err;
278 }
279
280 mmapstr = mmap_string_new("");
281 if (mmapstr == NULL) {
282 res = MAIL_ERROR_MEMORY;
283 goto close_db_flags;
284 }
285
286 r = mhdriver_get_cached_flags(cache_db_flags, mmapstr,
287 msg_info->msg_session, msg_info->msg_index, &flags);
288 if (r != MAIL_NO_ERROR) {
289 flags = mail_flags_new_empty();
290 if (flags == NULL) {
291 res = MAIL_ERROR_MEMORY;
292 goto free_mmapstr;
293 }
294 }
295
296 mmap_string_free(mmapstr);
297 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
298 }
299
300 msg_info->msg_flags = flags;
301
302 * result = flags;
303
304 return MAIL_NO_ERROR;
305
306 free_mmapstr:
307 mmap_string_free(mmapstr);
308 close_db_flags:
309 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
310 err:
311 return res;
312}
313
314static int mh_fetch_header(mailmessage * msg_info,
315 char ** result,
316 size_t * result_len)
317{
318 struct generic_message_t * msg;
319 int r;
320 char * msg_content;
321 size_t msg_length;
322
323 msg = msg_info->msg_data;
324 if (msg->msg_message != NULL) {
325 return mailmessage_generic_fetch_header(msg_info, result, result_len);
326 }
327 else {
328 r = mhdriver_fetch_header(get_ancestor_session(msg_info),
329 msg_info->msg_index, &msg_content, &msg_length);
330 if (r != MAIL_NO_ERROR)
331 return r;
332
333 * result = msg_content;
334 * result_len = msg_length;
335
336 return MAIL_NO_ERROR;
337 }
338}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h
new file mode 100644
index 0000000..f585708
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_CACHED_MESSAGE_H
37
38#define MHDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_message.c b/libetpan/src/driver/implementation/mh/mhdriver_message.c
new file mode 100644
index 0000000..0e486b4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_message.c
@@ -0,0 +1,213 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "mhdriver_tools.h"
40#include "mhdriver.h"
41#include "mailmh.h"
42
43#include <unistd.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <string.h>
49#include <stdlib.h>
50
51static int mh_prefetch(mailmessage * msg_info);
52
53static void mh_prefetch_free(struct generic_message_t * msg);
54
55static int mh_initialize(mailmessage * msg_info);
56
57static int mh_fetch_size(mailmessage * msg_info,
58 size_t * result);
59
60static int mh_fetch_header(mailmessage * msg_info,
61 char ** result,
62 size_t * result_len);
63
64static mailmessage_driver local_mh_message_driver = {
65 .msg_name = "mh",
66
67 .msg_initialize = mh_initialize,
68 .msg_uninitialize = mailmessage_generic_uninitialize,
69
70 .msg_flush = mailmessage_generic_flush,
71 .msg_check = NULL,
72
73 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
74
75 .msg_fetch = mailmessage_generic_fetch,
76 .msg_fetch_header = mh_fetch_header,
77 .msg_fetch_body = mailmessage_generic_fetch_body,
78 .msg_fetch_size = mh_fetch_size,
79 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
80 .msg_fetch_section = mailmessage_generic_fetch_section,
81 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
82 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
83 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
84 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
85
86 .msg_get_flags = NULL,
87};
88
89mailmessage_driver * mh_message_driver = &local_mh_message_driver;
90
91static int mh_prefetch(mailmessage * msg_info)
92{
93 struct generic_message_t * msg;
94 int r;
95 char * msg_content;
96 size_t msg_length;
97
98 r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index,
99 &msg_content, &msg_length);
100 if (r != MAIL_NO_ERROR)
101 return r;
102
103 msg = msg_info->msg_data;
104
105 msg->msg_message = msg_content;
106 msg->msg_length = msg_length;
107
108 return MAIL_NO_ERROR;
109}
110
111static void mh_prefetch_free(struct generic_message_t * msg)
112{
113 if (msg->msg_message != NULL) {
114 mmap_string_unref(msg->msg_message);
115 msg->msg_message = NULL;
116 }
117}
118
119static inline struct mh_session_state_data * get_data(mailmessage * msg)
120{
121 return msg->msg_session->sess_data;
122}
123
124static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg)
125{
126 return get_data(msg)->mh_cur_folder;
127}
128
129static int mh_initialize(mailmessage * msg_info)
130{
131 struct generic_message_t * msg;
132 int r;
133 char * uid;
134 char static_uid[PATH_MAX];
135 struct mailmh_msg_info * mh_msg_info;
136 chashdatum key;
137 chashdatum value;
138
139 key.data = &msg_info->msg_index;
140 key.len = sizeof(msg_info->msg_index);
141 r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value);
142 if (r < 0)
143 return MAIL_ERROR_INVAL;
144
145 mh_msg_info = value.data;
146
147 snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index,
148 (unsigned long) mh_msg_info->msg_mtime,
149 (unsigned long) mh_msg_info->msg_size);
150 uid = strdup(static_uid);
151 if (uid == NULL)
152 return MAIL_ERROR_MEMORY;
153
154 r = mailmessage_generic_initialize(msg_info);
155 if (r != MAIL_NO_ERROR) {
156 free(uid);
157 return r;
158 }
159
160 msg = msg_info->msg_data;
161 msg->msg_prefetch = mh_prefetch;
162 msg->msg_prefetch_free = mh_prefetch_free;
163 msg_info->msg_uid = uid;
164
165 return MAIL_NO_ERROR;
166}
167
168
169static int mh_fetch_size(mailmessage * msg_info,
170 size_t * result)
171{
172 int r;
173 size_t size;
174
175 r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size);
176 if (r != MAIL_NO_ERROR)
177 return r;
178
179 * result = size;
180
181 return MAIL_NO_ERROR;
182}
183
184
185
186
187static int mh_fetch_header(mailmessage * msg_info,
188 char ** result,
189 size_t * result_len)
190{
191 struct generic_message_t * msg;
192 int r;
193 char * msg_content;
194 size_t msg_length;
195
196 msg = msg_info->msg_data;
197 if (msg->msg_message != NULL) {
198
199 r = mailmessage_generic_fetch_header(msg_info, result, result_len);
200 return r;
201 }
202 else {
203 r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index,
204 &msg_content, &msg_length);
205 if (r != MAIL_NO_ERROR)
206 return r;
207
208 * result = msg_content;
209 * result_len = msg_length;
210
211 return MAIL_NO_ERROR;
212 }
213}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_message.h b/libetpan/src/driver/implementation/mh/mhdriver_message.h
new file mode 100644
index 0000000..2b11f3e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_MESSAGE_H
37
38#define MHDRIVER_MESSAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * mh_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_tools.c b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
new file mode 100644
index 0000000..b8bcf03
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
@@ -0,0 +1,484 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhdriver_tools.h"
37
38#include "mailmessage.h"
39#include "mhdriver.h"
40#include "mhdriver_cached.h"
41#include "maildriver_types.h"
42#include "mailmh.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mail_cache_db.h"
46
47#include <unistd.h>
48#include <sys/mman.h>
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <fcntl.h>
52#include <string.h>
53#include <stdlib.h>
54
55int mhdriver_mh_error_to_mail_error(int error)
56{
57 switch (error) {
58 case MAILMH_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case MAILMH_ERROR_FOLDER:
62 return MAIL_ERROR_FOLDER;
63
64 case MAILMH_ERROR_MEMORY:
65 return MAIL_ERROR_MEMORY;
66
67 case MAILMH_ERROR_FILE:
68 return MAIL_ERROR_FILE;
69
70 case MAILMH_ERROR_COULD_NOT_ALLOC_MSG:
71 return MAIL_ERROR_APPEND;
72
73 case MAILMH_ERROR_RENAME:
74 return MAIL_ERROR_RENAME;
75
76 case MAILMH_ERROR_MSG_NOT_FOUND:
77 return MAIL_ERROR_MSG_NOT_FOUND;
78
79 default:
80 return MAIL_ERROR_INVAL;
81 }
82}
83
84
85static inline struct mh_session_state_data * get_data(mailsession * session)
86{
87 return session->sess_data;
88}
89
90static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
91{
92 return get_data(session)->mh_cur_folder;
93}
94
95static inline struct mh_cached_session_state_data *
96cached_get_data(mailsession * session)
97{
98 return session->sess_data;
99}
100
101
102static inline mailsession * cached_get_ancestor(mailsession * session)
103{
104 return cached_get_data(session)->mh_ancestor;
105}
106
107static inline struct mh_session_state_data *
108cached_get_ancestor_data(mailsession * session)
109{
110 return get_data(cached_get_ancestor(session));
111}
112
113static inline struct mailmh_folder *
114cached_get_mh_cur_folder(mailsession * session)
115{
116 return get_mh_cur_folder(cached_get_ancestor(session));
117}
118
119int mhdriver_fetch_message(mailsession * session, uint32_t index,
120 char ** result, size_t * result_len)
121{
122 size_t size;
123 size_t cur_token;
124 struct mailmh_folder * folder;
125 int fd;
126 MMAPString * mmapstr;
127 char * str;
128 int res;
129 int r;
130
131 folder = get_mh_cur_folder(session);
132 if (folder == NULL) {
133 res = MAIL_ERROR_BAD_STATE;
134 goto err;
135 }
136
137 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
138
139 switch (r) {
140 case MAILMH_NO_ERROR:
141 break;
142
143 default:
144 res = mhdriver_mh_error_to_mail_error(r);
145 goto close;
146 }
147
148 r = mhdriver_fetch_size(session, index, &size);
149
150 switch (r) {
151 case MAILMH_NO_ERROR:
152 break;
153
154 default:
155 res = mhdriver_mh_error_to_mail_error(r);
156 goto close;
157 }
158
159 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
160 if (str == MAP_FAILED) {
161 res = MAIL_ERROR_FETCH;
162 goto close;
163 }
164
165 /* strip "From " header for broken implementations */
166 /* XXX - called twice, make a function */
167 cur_token = 0;
168 if (strncmp("From ", str, 5) == 0) {
169 cur_token += 5;
170
171 while (1) {
172 if (str[cur_token] == '\n') {
173 cur_token ++;
174 break;
175 }
176 if (cur_token >= size)
177 break;
178 cur_token ++;
179 }
180 }
181
182 mmapstr = mmap_string_new_len(str + cur_token, size - cur_token);
183 if (mmapstr == NULL) {
184 res = MAIL_ERROR_MEMORY;
185 goto unmap;
186 }
187
188 if (mmap_string_ref(mmapstr) != 0) {
189 res = MAIL_ERROR_MEMORY;
190 goto free_str;
191 }
192
193 munmap(str, size);
194 close(fd);
195
196 * result = mmapstr->str;
197 * result_len = mmapstr->len;
198
199 return MAIL_NO_ERROR;
200
201 free_str:
202 mmap_string_free(mmapstr);
203 unmap:
204 munmap(str, size);
205 close:
206 close(fd);
207 err:
208 return res;
209}
210
211
212int mhdriver_fetch_header(mailsession * session, uint32_t index,
213 char ** result, size_t * result_len)
214{
215 size_t size;
216 size_t cur_token;
217 size_t begin;
218 struct mailmh_folder * folder;
219 int fd;
220 MMAPString * mmapstr;
221 char * str;
222 int res;
223 int r;
224
225 folder = get_mh_cur_folder(session);
226 if (folder == NULL) {
227 res = MAIL_ERROR_BAD_STATE;
228 goto err;
229 }
230
231 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
232
233 switch (r) {
234 case MAILMH_NO_ERROR:
235 break;
236
237 default:
238 res = mhdriver_mh_error_to_mail_error(r);
239 goto close;
240 }
241
242 r = mhdriver_fetch_size(session, index, &size);
243
244 switch (r) {
245 case MAILMH_NO_ERROR:
246 break;
247
248 default:
249 res = mhdriver_mh_error_to_mail_error(r);
250 goto close;
251 }
252
253 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
254 if (str == MAP_FAILED) {
255 res = MAIL_ERROR_FETCH;
256 goto close;
257 }
258
259 /* strip "From " header for broken implementations */
260 cur_token = 0;
261 if (size > 5) {
262 if (strncmp("From ", str, 5) == 0) {
263 cur_token += 5;
264
265 while (1) {
266 if (str[cur_token] == '\n') {
267 cur_token ++;
268 break;
269 }
270 if (cur_token >= size)
271 break;
272 cur_token ++;
273 }
274 }
275 }
276
277 begin = cur_token;
278
279 while (1) {
280 r = mailimf_ignore_field_parse(str, size, &cur_token);
281 if (r == MAILIMF_NO_ERROR) {
282 /* do nothing */
283 }
284 else
285 break;
286 }
287 mailimf_crlf_parse(str, size, &cur_token);
288
289 mmapstr = mmap_string_new_len(str + begin, cur_token - begin);
290 if (mmapstr == NULL) {
291 res = MAIL_ERROR_MEMORY;
292 goto unmap;
293 }
294
295 if (mmap_string_ref(mmapstr) != 0) {
296 res = MAIL_ERROR_MEMORY;
297 goto free_str;
298 }
299
300 munmap(str, size);
301 close(fd);
302
303 * result = mmapstr->str;
304 * result_len = mmapstr->len;
305
306 return MAIL_NO_ERROR;
307
308 free_str:
309 mmap_string_free(mmapstr);
310 unmap:
311 munmap(str, size);
312 close:
313 close(fd);
314 err:
315 return res;
316}
317
318
319int mhdriver_fetch_size(mailsession * session, uint32_t index,
320 size_t * result)
321{
322 struct mailmh_folder * folder;
323 int r;
324 struct stat buf;
325 char * name;
326
327 folder = get_mh_cur_folder(session);
328 if (folder == NULL)
329 return MAIL_ERROR_FETCH;
330
331 r = mailmh_folder_get_message_filename(folder, index, &name);
332
333 switch (r) {
334 case MAILMH_NO_ERROR:
335 break;
336
337 default:
338 return mhdriver_mh_error_to_mail_error(r);
339 }
340
341 r = stat(name, &buf);
342 free(name);
343 if (r == -1)
344 return MAIL_ERROR_FETCH;
345
346 * result = buf.st_size;
347
348 return MAIL_NO_ERROR;
349}
350
351int
352mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
353 MMAPString * mmapstr,
354 mailsession * session,
355 uint32_t num,
356 struct mail_flags ** result)
357{
358 int r;
359 char keyname[PATH_MAX];
360 struct mail_flags * flags;
361 int res;
362 struct mailmh_msg_info * msg_info;
363 chashdatum key;
364 chashdatum data;
365 struct mailmh_folder * folder;
366
367 folder = cached_get_mh_cur_folder(session);
368#if 0
369 msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num);
370 if (msg_info == NULL)
371 return MAIL_ERROR_CACHE_MISS;
372#endif
373 key.data = &num;
374 key.len = sizeof(num);
375 r = chash_get(folder->fl_msgs_hash, &key, &data);
376 if (r < 0)
377 return MAIL_ERROR_CACHE_MISS;
378 msg_info = data.data;
379
380 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
381 num, (unsigned long) msg_info->msg_mtime,
382 (unsigned long) msg_info->msg_size);
383
384 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
385 if (r != MAIL_NO_ERROR) {
386 res = r;
387 goto err;
388 }
389
390 * result = flags;
391
392 return MAIL_NO_ERROR;
393
394 err:
395 return res;
396}
397
398int
399mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
400 MMAPString * mmapstr,
401 char * uid,
402 struct mail_flags * flags)
403{
404 int r;
405 char keyname[PATH_MAX];
406 int res;
407
408 snprintf(keyname, PATH_MAX, "%s-flags", uid);
409
410 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
411 if (r != MAIL_NO_ERROR) {
412 res = r;
413 goto err;
414 }
415
416 return MAIL_NO_ERROR;
417
418 err:
419 return res;
420}
421
422
423int mh_get_messages_list(struct mailmh_folder * folder,
424 mailsession * session, mailmessage_driver * driver,
425 struct mailmessage_list ** result)
426{
427 unsigned int i;
428 struct mailmessage_list * env_list;
429 int r;
430 carray * tab;
431 int res;
432
433 tab = carray_new(128);
434 if (tab == NULL) {
435 res = MAIL_ERROR_MEMORY;
436 goto err;
437 }
438
439 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
440 struct mailmh_msg_info * mh_info;
441 mailmessage * msg;
442
443 mh_info = carray_get(folder->fl_msgs_tab, i);
444 if (mh_info == NULL)
445 continue;
446
447 msg = mailmessage_new();
448 if (msg == NULL) {
449 res = MAIL_ERROR_MEMORY;
450 goto free_list;
451 }
452
453 r = mailmessage_init(msg, session, driver,
454 mh_info->msg_index, mh_info->msg_size);
455 if (r != MAIL_NO_ERROR) {
456 res = r;
457 goto free_list;
458 }
459
460 r = carray_add(tab, msg, NULL);
461 if (r < 0) {
462 mailmessage_free(msg);
463 res = MAIL_ERROR_MEMORY;
464 goto free_list;
465 }
466 }
467
468 env_list = mailmessage_list_new(tab);
469 if (env_list == NULL) {
470 res = MAIL_ERROR_MEMORY;
471 goto free_list;
472 }
473
474 * result = env_list;
475
476 return MAIL_NO_ERROR;
477
478 free_list:
479 for(i = 0 ; i < carray_count(tab) ; i ++)
480 mailmessage_free(carray_get(tab, i));
481 carray_free(tab);
482 err:
483 return res;
484}
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_tools.h b/libetpan/src/driver/implementation/mh/mhdriver_tools.h
new file mode 100644
index 0000000..7b8928e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_tools.h
@@ -0,0 +1,80 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_TOOLS_H
37
38#define MHDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "mail_cache_db_types.h"
42#include "mailmh.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int mhdriver_mh_error_to_mail_error(int error);
49
50int mhdriver_fetch_message(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int mhdriver_fetch_header(mailsession * session, uint32_t index,
54 char ** result, size_t * result_len);
55
56int mhdriver_fetch_size(mailsession * session, uint32_t index,
57 size_t * result);
58
59int
60mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
61 MMAPString * mmapstr,
62 mailsession * session,
63 uint32_t num,
64 struct mail_flags ** result);
65
66int
67mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
68 MMAPString * mmapstr,
69 char * uid,
70 struct mail_flags * flags);
71
72int mh_get_messages_list(struct mailmh_folder * folder,
73 mailsession * session, mailmessage_driver * driver,
74 struct mailmessage_list ** result);
75
76#ifdef __cplusplus
77}
78#endif
79
80#endif
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_types.h b/libetpan/src/driver/implementation/mh/mhdriver_types.h
new file mode 100644
index 0000000..45afb64
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_types.h
@@ -0,0 +1,100 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHDRIVER_TYPES_H
37
38#define MHDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailmh.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52struct mh_session_state_data {
53 struct mailmh * mh_session;
54
55 struct mailmh_folder * mh_cur_folder;
56
57 clist * mh_subscribed_list;
58};
59
60enum {
61 MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
62 MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
63};
64
65struct mh_cached_session_state_data {
66 mailsession * mh_ancestor;
67 char * mh_quoted_mb;
68 char mh_cache_directory[PATH_MAX];
69 char mh_flags_directory[PATH_MAX];
70 struct mail_flags_store * mh_flags_store;
71};
72
73/* mh storage */
74
75/*
76 mh_mailstorage is the state data specific to the MH storage.
77
78 - pathname is the root path of the MH storage.
79
80 - cached if this value is != 0, a persistant cache will be
81 stored on local system.
82
83 - cache_directory is the location of the cache.
84
85 - flags_directory is the location of the flags.
86*/
87
88struct mh_mailstorage {
89 char * mh_pathname;
90
91 int mh_cached;
92 char * mh_cache_directory;
93 char * mh_flags_directory;
94};
95
96#ifdef __cplusplus
97}
98#endif
99
100#endif
diff --git a/libetpan/src/driver/implementation/mh/mhstorage.c b/libetpan/src/driver/implementation/mh/mhstorage.c
new file mode 100644
index 0000000..e7fc2f0
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhstorage.c
@@ -0,0 +1,192 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mhstorage.h"
37
38#include "mhdriver.h"
39#include "mhdriver_cached.h"
40#include "mail.h"
41
42#include <stdlib.h>
43#include <string.h>
44
45/* mh storage */
46
47static int mh_mailstorage_connect(struct mailstorage * storage);
48static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
49 char * pathname, mailsession ** result);
50static void mh_mailstorage_uninitialize(struct mailstorage * storage);
51
52static mailstorage_driver mh_mailstorage_driver = {
53 .sto_name = "mh",
54 .sto_connect = mh_mailstorage_connect,
55 .sto_get_folder_session = mh_mailstorage_get_folder_session,
56 .sto_uninitialize = mh_mailstorage_uninitialize,
57};
58
59int mh_mailstorage_init(struct mailstorage * storage,
60 char * mh_pathname, int mh_cached,
61 char * mh_cache_directory, char * mh_flags_directory)
62{
63 struct mh_mailstorage * mh_storage;
64
65 mh_storage = malloc(sizeof(* mh_storage));
66 if (mh_storage == NULL)
67 goto err;
68
69 mh_storage->mh_pathname = strdup(mh_pathname);
70 if (mh_storage->mh_pathname == NULL)
71 goto free;
72
73 mh_storage->mh_cached = mh_cached;
74
75 if (mh_cached && (mh_cache_directory != NULL) &&
76 (mh_flags_directory != NULL)) {
77 mh_storage->mh_cache_directory = strdup(mh_cache_directory);
78 if (mh_storage->mh_cache_directory == NULL)
79 goto free_pathname;
80 mh_storage->mh_flags_directory = strdup(mh_flags_directory);
81 if (mh_storage->mh_flags_directory == NULL)
82 goto free_cache_directory;
83 }
84 else {
85 mh_storage->mh_cached = FALSE;
86 mh_storage->mh_cache_directory = NULL;
87 mh_storage->mh_flags_directory = NULL;
88 }
89
90 storage->sto_data = mh_storage;
91 storage->sto_driver = &mh_mailstorage_driver;
92
93 return MAIL_NO_ERROR;
94
95 free_cache_directory:
96 free(mh_storage->mh_cache_directory);
97 free_pathname:
98 free(mh_storage->mh_pathname);
99 free:
100 free(mh_storage);
101 err:
102 return MAIL_ERROR_MEMORY;
103}
104
105static void mh_mailstorage_uninitialize(struct mailstorage * storage)
106{
107 struct mh_mailstorage * mh_storage;
108
109 mh_storage = storage->sto_data;
110 if (mh_storage->mh_flags_directory != NULL)
111 free(mh_storage->mh_flags_directory);
112 if (mh_storage->mh_cache_directory != NULL)
113 free(mh_storage->mh_cache_directory);
114 free(mh_storage->mh_pathname);
115 free(mh_storage);
116
117 storage->sto_data = NULL;
118}
119
120static int mh_mailstorage_connect(struct mailstorage * storage)
121{
122 struct mh_mailstorage * mh_storage;
123 mailsession_driver * driver;
124 int r;
125 int res;
126 mailsession * session;
127
128 mh_storage = storage->sto_data;
129
130 if (mh_storage->mh_cached)
131 driver = mh_cached_session_driver;
132 else
133 driver = mh_session_driver;
134
135 session = mailsession_new(driver);
136 if (session == NULL) {
137 res = MAIL_ERROR_MEMORY;
138 goto err;
139 }
140
141 if (mh_storage->mh_cached) {
142 r = mailsession_parameters(session,
143 MHDRIVER_CACHED_SET_CACHE_DIRECTORY,
144 mh_storage->mh_cache_directory);
145 if (r != MAIL_NO_ERROR) {
146 res = r;
147 goto free;
148 }
149
150 r = mailsession_parameters(session,
151 MHDRIVER_CACHED_SET_FLAGS_DIRECTORY,
152 mh_storage->mh_flags_directory);
153 if (r != MAIL_NO_ERROR) {
154 res = r;
155 goto free;
156 }
157 }
158
159 r = mailsession_connect_path(session, mh_storage->mh_pathname);
160 switch (r) {
161 case MAIL_NO_ERROR_NON_AUTHENTICATED:
162 case MAIL_NO_ERROR_AUTHENTICATED:
163 case MAIL_NO_ERROR:
164 break;
165 default:
166 res = r;
167 goto free;
168 }
169
170 storage->sto_session = session;
171
172 return MAIL_NO_ERROR;
173
174 free:
175 mailsession_free(session);
176 err:
177 return res;
178}
179
180static int mh_mailstorage_get_folder_session(struct mailstorage * storage,
181 char * pathname, mailsession ** result)
182{
183 int r;
184
185 r = mailsession_select_folder(storage->sto_session, pathname);
186 if (r != MAIL_NO_ERROR)
187 return r;
188
189 * result = storage->sto_session;
190
191 return MAIL_NO_ERROR;
192}
diff --git a/libetpan/src/driver/implementation/mh/mhstorage.h b/libetpan/src/driver/implementation/mh/mhstorage.h
new file mode 100644
index 0000000..be86007
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhstorage.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MHSTORAGE_H
37
38#define MHSTORAGE_H
39
40#include <libetpan/mhdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mh_mailstorage_init is the constructor for a MH storage
48
49 @param pathname is the filename the root path of the MH storage.
50
51 @param cached if this value is != 0, a persistant cache will be
52 stored on local system.
53
54 @param cache_directory is the location of the cache.
55
56 @param flags_directory is the location of the flags.
57*/
58
59int mh_mailstorage_init(struct mailstorage * storage,
60 char * mh_pathname, int mh_cached,
61 char * mh_cache_directory, char * mh_flags_directory);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/src/driver/implementation/mime-message/mime_message_driver.c b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
new file mode 100644
index 0000000..06defbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
@@ -0,0 +1,914 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mime_message_driver.h"
37
38#include "libetpan-config.h"
39
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "mailmessage.h"
48#include "mailmessage_tools.h"
49#include "maildriver_tools.h"
50
51#if 0
52static FILE * get_mime_tmp_file(mailmessage * msg,
53 char * filename, size_t size)
54{
55 int fd;
56 mode_t old_mask;
57 FILE * f;
58
59 if (msg->msg_data == NULL)
60 return NULL;
61
62 snprintf(filename, size, "%s/libetpan-mime-XXXXXX",
63 (char *) msg->msg_data);
64
65 old_mask = umask(0077);
66 fd = mkstemp(filename);
67 umask(old_mask);
68 if (fd == -1)
69 return NULL;
70
71 f = fdopen(fd, "r+");
72 if (f == NULL) {
73 close(fd);
74 unlink(filename);
75 }
76
77 return f;
78}
79#endif
80
81int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir)
82{
83#if 0
84 if (msg->msg_data != NULL)
85 free(msg->msg_data);
86
87 msg->msg_data = strdup(tmpdir);
88 if (msg->msg_data == NULL)
89 return MAIL_ERROR_MEMORY;
90
91#endif
92 return MAIL_NO_ERROR;
93}
94
95void mime_message_detach_mime(mailmessage * msg)
96{
97 msg->msg_mime = NULL;
98}
99
100mailmessage * mime_message_init(struct mailmime * mime)
101{
102 mailmessage * msg;
103 int r;
104
105 msg = mailmessage_new();
106 if (msg == NULL)
107 goto err;
108
109 r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0);
110 if (r != MAIL_NO_ERROR)
111 goto free;
112
113 if (mime != NULL) {
114 mailmime_free(msg->msg_mime);
115 msg->msg_mime = mime;
116 }
117
118 return msg;
119
120 free:
121 mailmessage_free(msg);
122 err:
123 return NULL;
124}
125
126static int initialize(mailmessage * msg)
127{
128 struct mailmime * mime;
129 int res;
130
131 mime = mailmime_new_message_data(NULL);
132 if (mime == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto err;
135 }
136
137 msg->msg_mime = mime;
138
139 return MAIL_NO_ERROR;
140
141 err:
142 return res;
143}
144
145static void uninitialize(mailmessage * msg)
146{
147 /* tmp dir name */
148 if (msg->msg_data != NULL)
149 free(msg->msg_data);
150
151 if (msg->msg_mime != NULL)
152 mailmime_free(msg->msg_mime);
153 msg->msg_mime = NULL;
154}
155
156static void flush(mailmessage * msg)
157{
158 /* do nothing */
159}
160
161static void check(mailmessage * msg)
162{
163 /* do nothing */
164}
165
166static void fetch_result_free(mailmessage * msg_info, char * content)
167{
168 mmap_string_unref(content);
169}
170
171#if 0
172static int file_to_mmapstr(FILE * f,
173 char ** result, size_t * result_len)
174{
175 int fd;
176 char * data;
177 struct stat buf;
178 MMAPString * mmapstr;
179 int res;
180 int r;
181
182 fd = fileno(f);
183 if (fd == -1) {
184 res = MAIL_ERROR_FILE;
185
186 goto err;
187 }
188
189 fflush(f);
190 r = fstat(fd, &buf);
191 if (r == -1) {
192 res = MAIL_ERROR_FILE;
193
194 goto err;
195 }
196
197 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
198 if (data == MAP_FAILED) {
199 res = MAIL_ERROR_FILE;
200
201 goto err;
202 }
203
204 mmapstr = mmap_string_new_len(data, buf.st_size);
205 if (mmapstr == NULL) {
206 res = MAIL_ERROR_MEMORY;
207
208 goto unmap;
209 }
210
211 munmap(data, buf.st_size);
212
213 r = mmap_string_ref(mmapstr);
214 if (r != 0) {
215 res = MAIL_ERROR_MEMORY;
216
217 goto err;
218 }
219
220 * result = mmapstr->str;
221 * result_len = mmapstr->len;
222
223 return MAIL_NO_ERROR;
224
225 unmap:
226 munmap(data, buf.st_size);
227 err:
228 return res;
229}
230#endif
231
232#if 0
233static int file_body_to_mmapstr(FILE * f,
234 char ** result, size_t * result_len)
235{
236 int fd;
237 char * data;
238 struct stat buf;
239 MMAPString * mmapstr;
240 size_t cur_token;
241 int res;
242 int r;
243
244 fd = fileno(f);
245 if (fd == -1) {
246 res = MAIL_ERROR_FILE;
247
248 goto err;
249 }
250
251 fflush(f);
252 r = fstat(fd, &buf);
253 if (r == -1) {
254 res = MAIL_ERROR_FILE;
255
256 goto err;
257 }
258
259 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
260 if (data == MAP_FAILED) {
261 res = MAIL_ERROR_FILE;
262
263 goto err;
264 }
265
266 cur_token = 0;
267
268 /* skip header */
269
270 while (1) {
271 r = mailimf_ignore_field_parse(data,
272 buf.st_size, &cur_token);
273 if (r == MAILIMF_NO_ERROR) {
274 /* do nothing */
275 }
276 else
277 break;
278 }
279
280 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
281 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
282 res = maildriver_imf_error_to_mail_error(r);
283 goto unmap;
284 }
285
286 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
287 if (mmapstr == NULL) {
288 res = MAIL_ERROR_MEMORY;
289
290 goto unmap;
291 }
292
293 munmap(data, buf.st_size);
294
295 r = mmap_string_ref(mmapstr);
296 if (r != 0) {
297 res = MAIL_ERROR_MEMORY;
298
299 goto err;
300 }
301
302 * result = mmapstr->str;
303 * result_len = mmapstr->len;
304
305 return MAIL_NO_ERROR;
306
307 unmap:
308 munmap(data, buf.st_size);
309 err:
310 return res;
311}
312#endif
313
314
315static int body_to_mmapstr(char * data, size_t size,
316 char ** result, size_t * result_len)
317{
318 MMAPString * mmapstr;
319 size_t cur_token;
320 int res;
321 int r;
322
323 cur_token = 0;
324
325 /* skip header */
326
327 while (1) {
328 r = mailimf_ignore_field_parse(data, size, &cur_token);
329 if (r == MAILIMF_NO_ERROR) {
330 /* do nothing */
331 }
332 else
333 break;
334 }
335
336 r = mailimf_crlf_parse(data, size, &cur_token);
337 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
338 res = maildriver_imf_error_to_mail_error(r);
339 goto err;
340 }
341
342 mmapstr = mmap_string_new_len(data + cur_token, size - cur_token);
343 if (mmapstr == NULL) {
344 res = MAIL_ERROR_MEMORY;
345
346 goto err;
347 }
348
349 r = mmap_string_ref(mmapstr);
350 if (r != 0) {
351 mmap_string_free(mmapstr);
352 res = MAIL_ERROR_MEMORY;
353
354 goto err;
355 }
356
357 * result = mmapstr->str;
358 * result_len = mmapstr->len;
359
360 return MAIL_NO_ERROR;
361
362 err:
363 return res;
364}
365
366
367#if 0
368static int file_body_body_to_mmapstr(FILE * f,
369 char ** result, size_t * result_len)
370{
371 int fd;
372 char * data;
373 struct stat buf;
374 MMAPString * mmapstr;
375 size_t cur_token;
376 int res;
377 int r;
378
379 fd = fileno(f);
380 if (fd == -1) {
381 res = MAIL_ERROR_FILE;
382
383 goto err;
384 }
385
386 fflush(f);
387 r = fstat(fd, &buf);
388 if (r == -1) {
389 res = MAIL_ERROR_FILE;
390
391 goto err;
392 }
393
394 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
395 if (data == MAP_FAILED) {
396 res = MAIL_ERROR_FILE;
397
398 goto err;
399 }
400
401 cur_token = 0;
402
403 /* skip header */
404
405 /* MIME header */
406
407 while (1) {
408 r = mailimf_ignore_field_parse(data,
409 buf.st_size, &cur_token);
410 if (r == MAILIMF_NO_ERROR) {
411 /* do nothing */
412 }
413 else
414 break;
415 }
416
417 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
418 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
419 res = maildriver_imf_error_to_mail_error(r);
420 goto unmap;
421 }
422
423 /* headers */
424
425 while (1) {
426 r = mailimf_ignore_field_parse(data,
427 buf.st_size, &cur_token);
428 if (r == MAILIMF_NO_ERROR) {
429 /* do nothing */
430 }
431 else
432 break;
433 }
434
435 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
436 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
437 res = maildriver_imf_error_to_mail_error(r);
438 goto unmap;
439 }
440
441 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
442 if (mmapstr == NULL) {
443 res = MAIL_ERROR_MEMORY;
444
445 goto unmap;
446 }
447
448 munmap(data, buf.st_size);
449
450 r = mmap_string_ref(mmapstr);
451 if (r != 0) {
452 res = MAIL_ERROR_MEMORY;
453
454 goto err;
455 }
456
457 * result = mmapstr->str;
458 * result_len = mmapstr->len;
459
460 return MAIL_NO_ERROR;
461
462 unmap:
463 munmap(data, buf.st_size);
464 err:
465 return res;
466}
467#endif
468
469static int body_body_to_mmapstr(char * data, size_t size,
470 char ** result, size_t * result_len)
471{
472 MMAPString * mmapstr;
473 size_t cur_token;
474 int res;
475 int r;
476
477 cur_token = 0;
478
479 /* skip header */
480
481 /* MIME header */
482
483 while (1) {
484 r = mailimf_ignore_field_parse(data, size, &cur_token);
485 if (r == MAILIMF_NO_ERROR) {
486 /* do nothing */
487 }
488 else
489 break;
490 }
491
492 r = mailimf_crlf_parse(data, size, &cur_token);
493 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
494 res = maildriver_imf_error_to_mail_error(r);
495 goto err;
496 }
497
498 return body_to_mmapstr(data + cur_token, size - cur_token,
499 result, result_len);
500
501 err:
502 return res;
503}
504
505
506static int fetch_section(mailmessage * msg_info,
507 struct mailmime * mime,
508 char ** result, size_t * result_len)
509{
510 int r;
511#if 0
512 FILE * f;
513#endif
514 int res;
515 int col;
516#if 0
517 char filename[PATH_MAX];
518#endif
519 MMAPString * str;
520
521 if (msg_info->msg_mime == NULL)
522 return MAIL_ERROR_INVAL;
523
524#if 0
525 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
526 if (f == NULL) {
527 res = MAIL_ERROR_FILE;
528 goto err;
529 }
530#endif
531
532 str = mmap_string_new("");
533 if (str == NULL) {
534 res = MAILIMF_ERROR_MEMORY;
535 goto err;
536 }
537
538 col = 0;
539 r = mailmime_write_mem(str, &col, mime);
540 if (r != MAILIMF_NO_ERROR) {
541 res = maildriver_imf_error_to_mail_error(r);
542 goto free;
543 }
544
545#if 0
546 if (mime->mm_parent == NULL)
547 r = file_to_mmapstr(f, result, result_len);
548 else
549 r = file_body_to_mmapstr(f, result, result_len);
550#endif
551 if (mime->mm_parent == NULL) {
552 r = mmap_string_ref(str);
553 if (r < 0) {
554 res = MAIL_ERROR_MEMORY;
555 goto free;
556 }
557
558 * result = str->str;
559 * result_len = str->len;
560
561 r = MAIL_NO_ERROR;
562 }
563 else {
564 r = body_to_mmapstr(str->str, str->len, result, result_len);
565 if (r == MAIL_NO_ERROR) {
566 mmap_string_free(str);
567 }
568 }
569
570 if (r != MAIL_NO_ERROR) {
571 res = r;
572 goto free;
573 }
574
575#if 0
576 fclose(f);
577 unlink(filename);
578#endif
579
580 return MAIL_NO_ERROR;
581
582 free:
583#if 0
584 fclose(f);
585 unlink(filename);
586#endif
587 mmap_string_free(str);
588 err:
589 return res;
590}
591
592
593static int fetch_section_header(mailmessage * msg_info,
594 struct mailmime * mime,
595 char ** result, size_t * result_len)
596{
597 int r;
598#if 0
599 FILE * f;
600#endif
601 int res;
602 int col;
603#if 0
604 char filename[PATH_MAX];
605#endif
606 MMAPString * str;
607
608 if (msg_info->msg_mime == NULL)
609 return MAIL_ERROR_INVAL;
610
611#if 0
612 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
613 if (f == NULL) {
614 res = MAIL_ERROR_FILE;
615 goto err;
616 }
617#endif
618
619 str = mmap_string_new("");
620 if (str == NULL) {
621 res = MAIL_ERROR_MEMORY;
622 goto err;
623 }
624
625 col = 0;
626 if (mime->mm_type == MAILMIME_MESSAGE) {
627 if (mime->mm_data.mm_message.mm_fields != NULL) {
628#if 0
629 r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
630#endif
631 r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields);
632 if (r != MAILIMF_NO_ERROR) {
633 res = maildriver_imf_error_to_mail_error(r);
634 goto free;
635 }
636#if 0
637 mailimf_string_write(f, &col, "\r\n", 2);
638#endif
639 mailimf_string_write_mem(str, &col, "\r\n", 2);
640 }
641 }
642
643 r = mmap_string_ref(str);
644 if (r < 0) {
645 res = MAIL_ERROR_MEMORY;
646 goto free;
647 }
648
649#if 0
650 r = file_to_mmapstr(f, result, result_len);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto free;
654 }
655#endif
656 * result = str->str;
657 * result_len = str->len;
658
659#if 0
660 fclose(f);
661 unlink(filename);
662#endif
663
664 return MAIL_NO_ERROR;
665
666#if 0
667 close:
668 fclose(f);
669 unlink(filename);
670#endif
671 free:
672 mmap_string_free(str);
673 err:
674 return res;
675}
676
677
678static int fetch_section_mime(mailmessage * msg_info,
679 struct mailmime * mime,
680 char ** result, size_t * result_len)
681{
682 int r;
683#if 0
684 FILE * f;
685#endif
686 int res;
687 int col;
688#if 0
689 char filename[PATH_MAX];
690#endif
691 MMAPString * str;
692
693 if (msg_info->msg_mime == NULL)
694 return MAIL_ERROR_INVAL;
695
696 str = mmap_string_new("");
697 if (str == NULL) {
698 res = MAIL_ERROR_MEMORY;
699 goto err;
700 }
701
702#if 0
703 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
704 if (f == NULL) {
705 res = MAIL_ERROR_FILE;
706 goto err;
707 }
708#endif
709
710 col = 0;
711 if (mime->mm_content_type != NULL) {
712#if 0
713 r = mailmime_content_write(f, &col, mime->mm_content_type);
714#endif
715 r = mailmime_content_write_mem(str, &col, mime->mm_content_type);
716 if (r != MAILIMF_NO_ERROR) {
717 res = maildriver_imf_error_to_mail_error(r);
718 goto free;
719 }
720 }
721 if (mime->mm_mime_fields != NULL) {
722 r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields);
723 if (r != MAILIMF_NO_ERROR) {
724 res = maildriver_imf_error_to_mail_error(r);
725 goto free;
726 }
727 }
728 mailimf_string_write_mem(str, &col, "\r\n", 2);
729
730#if 0
731 r = file_to_mmapstr(f, result, result_len);
732 if (r != MAIL_NO_ERROR) {
733 res = r;
734 goto free;
735 }
736
737 fclose(f);
738 unlink(filename);
739#endif
740
741 r = mmap_string_ref(str);
742 if (r < 0) {
743 res = MAIL_ERROR_MEMORY;
744 goto free;
745 }
746
747 * result = str->str;
748 * result_len = str->len;
749
750 return MAIL_NO_ERROR;
751
752#if 0
753 close:
754 fclose(f);
755 unlink(filename);
756#endif
757 free:
758 mmap_string_free(str);
759 err:
760 return res;
761}
762
763
764
765static int fetch_section_body(mailmessage * msg_info,
766 struct mailmime * mime,
767 char ** result, size_t * result_len)
768{
769 int r;
770#if 0
771 FILE * f;
772#endif
773 int res;
774 int col;
775#if 0
776 char filename[PATH_MAX];
777#endif
778 MMAPString * str;
779
780 if (msg_info->msg_mime == NULL)
781 return MAIL_ERROR_INVAL;
782
783 str = mmap_string_new("");
784 if (str == NULL) {
785 res = MAIL_ERROR_MEMORY;
786 goto err;
787 }
788
789#if 0
790 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
791 if (f == NULL) {
792 res = MAIL_ERROR_FILE;
793 goto err;
794 }
795#endif
796
797 col = 0;
798 if (mime->mm_mime_fields != NULL) {
799#if 0
800 r = mailmime_write(f, &col, mime);
801#endif
802 r = mailmime_write_mem(str, &col, mime);
803 if (r != MAILIMF_NO_ERROR) {
804 res = maildriver_imf_error_to_mail_error(r);
805 goto free;
806 }
807 }
808
809 if (mime->mm_type == MAILMIME_MESSAGE)
810 r = body_body_to_mmapstr(str->str, str->len, result, result_len);
811 else
812 r = body_to_mmapstr(str->str, str->len, result, result_len);
813
814 if (r != MAIL_NO_ERROR) {
815 res = r;
816 goto free;
817 }
818
819 mmap_string_free(str);
820
821#if 0
822 fclose(f);
823 unlink(filename);
824#endif
825
826 return MAIL_NO_ERROR;
827
828#if 0
829 close:
830 fclose(f);
831 unlink(filename);
832#endif
833 free:
834 mmap_string_free(str);
835 err:
836 return res;
837}
838
839
840static int get_bodystructure(mailmessage * msg_info,
841 struct mailmime ** result)
842{
843 if (msg_info->msg_mime == NULL)
844 return MAIL_ERROR_INVAL;
845
846 * result = msg_info->msg_mime;
847
848 return MAIL_NO_ERROR;
849}
850
851
852static int fetch(mailmessage * msg_info,
853 char ** result, size_t * result_len)
854{
855 return fetch_section(msg_info, msg_info->msg_mime, result, result_len);
856}
857
858static int fetch_header(mailmessage * msg_info,
859 char ** result, size_t * result_len)
860{
861 return fetch_section_header(msg_info,
862 msg_info->msg_mime, result, result_len);
863}
864
865static int fetch_body(mailmessage * msg_info,
866 char ** result, size_t * result_len)
867{
868 return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len);
869}
870
871
872static int fetch_size(mailmessage * msg_info,
873 size_t * result)
874{
875 char * msg;
876 int r;
877
878 r = fetch(msg_info, &msg, result);
879 if (r != MAIL_NO_ERROR) {
880 return r;
881 }
882
883 fetch_result_free(msg_info, msg);
884
885 return MAIL_NO_ERROR;
886}
887
888
889static mailmessage_driver local_mime_message_driver = {
890 .msg_name = "mime",
891
892 .msg_initialize = initialize,
893 .msg_uninitialize = uninitialize,
894
895 .msg_flush = flush,
896 .msg_check = check,
897
898 .msg_fetch_result_free = fetch_result_free,
899
900 .msg_fetch = fetch,
901 .msg_fetch_header = fetch_header,
902 .msg_fetch_body = fetch_body,
903 .msg_fetch_size = fetch_size,
904 .msg_get_bodystructure = get_bodystructure,
905 .msg_fetch_section = fetch_section,
906 .msg_fetch_section_header = fetch_section_header,
907 .msg_fetch_section_mime = fetch_section_mime,
908 .msg_fetch_section_body = fetch_section_body,
909 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
910
911 .msg_get_flags = NULL,
912};
913
914mailmessage_driver * mime_message_driver = &local_mime_message_driver;
diff --git a/libetpan/src/driver/implementation/mime-message/mime_message_driver.h b/libetpan/src/driver/implementation/mime-message/mime_message_driver.h
new file mode 100644
index 0000000..6cc3c5b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mime-message/mime_message_driver.h
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MIME_MESSAGE_DRIVER_H
37
38#define MIME_MESSAGE_DRIVER_H
39
40#include <libetpan/mailmessage.h>
41
42#define LIBETPAN_MIME_MESSAGE
43
44extern mailmessage_driver * mime_message_driver;
45
46mailmessage * mime_message_init(struct mailmime * mime);
47
48void mime_message_detach_mime(mailmessage * msg);
49
50/* deprecated */
51int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir);
52
53#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.c b/libetpan/src/driver/implementation/nntp/nntpdriver.c
new file mode 100644
index 0000000..15b764f
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.c
@@ -0,0 +1,1180 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail.h"
42#include "mailmessage.h"
43#include "nntpdriver_tools.h"
44#include "maildriver_tools.h"
45#include "nntpdriver_message.h"
46
47static int nntpdriver_initialize(mailsession * session);
48
49static void nntpdriver_uninitialize(mailsession * session);
50
51static int nntpdriver_parameters(mailsession * session,
52 int id, void * value);
53
54static int nntpdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int nntpdriver_login(mailsession * session,
57 char * userid, char * password);
58
59static int nntpdriver_logout(mailsession * session);
60
61static int nntpdriver_status_folder(mailsession * session, char * mb,
62 uint32_t * result_messages,
63 uint32_t * result_recent,
64 uint32_t * result_unseen);
65
66static int nntpdriver_messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int nntpdriver_append_message(mailsession * session,
70 char * message, size_t size);
71
72static int nntpdriver_append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int
76nntpdriver_get_envelopes_list(mailsession * session,
77 struct mailmessage_list * env_list);
78
79
80static int nntpdriver_get_messages_list(mailsession * session,
81 struct mailmessage_list ** result);
82
83static int nntpdriver_list_folders(mailsession * session, char * mb,
84 struct mail_list ** result);
85
86static int nntpdriver_lsub_folders(mailsession * session, char * mb,
87 struct mail_list ** result);
88
89static int nntpdriver_subscribe_folder(mailsession * session, char * mb);
90
91static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb);
92
93static int nntpdriver_get_message(mailsession * session,
94 uint32_t num, mailmessage ** result);
95
96static int nntpdriver_get_message_by_uid(mailsession * session,
97 const char * uid,
98 mailmessage ** result);
99
100static int nntpdriver_noop(mailsession * session);
101
102static mailsession_driver local_nntp_session_driver = {
103 .sess_name = "nntp",
104
105 .sess_initialize = nntpdriver_initialize,
106 .sess_uninitialize = nntpdriver_uninitialize,
107
108 .sess_parameters = nntpdriver_parameters,
109
110 .sess_connect_stream = nntpdriver_connect_stream,
111 .sess_connect_path = NULL,
112 .sess_starttls = NULL,
113 .sess_login = nntpdriver_login,
114 .sess_logout = nntpdriver_logout,
115 .sess_noop = nntpdriver_noop,
116
117 .sess_build_folder_name = NULL,
118 .sess_create_folder = NULL,
119 .sess_delete_folder = NULL,
120 .sess_rename_folder = NULL,
121 .sess_check_folder = NULL,
122 .sess_examine_folder = NULL,
123 .sess_select_folder = nntpdriver_select_folder,
124 .sess_expunge_folder = NULL,
125 .sess_status_folder = nntpdriver_status_folder,
126 .sess_messages_number = nntpdriver_messages_number,
127 .sess_recent_number = nntpdriver_messages_number,
128 .sess_unseen_number = nntpdriver_messages_number,
129 .sess_list_folders = nntpdriver_list_folders,
130 .sess_lsub_folders = nntpdriver_lsub_folders,
131 .sess_subscribe_folder = nntpdriver_subscribe_folder,
132 .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder,
133
134 .sess_append_message = nntpdriver_append_message,
135 .sess_append_message_flags = nntpdriver_append_message_flags,
136 .sess_copy_message = NULL,
137 .sess_move_message = NULL,
138
139 .sess_get_messages_list = nntpdriver_get_messages_list,
140 .sess_get_envelopes_list = nntpdriver_get_envelopes_list,
141 .sess_remove_message = NULL,
142#if 0
143 .sess_search_messages = maildriver_generic_search_messages,
144#endif
145
146 .sess_get_message = nntpdriver_get_message,
147 .sess_get_message_by_uid = nntpdriver_get_message_by_uid,
148};
149
150
151mailsession_driver * nntp_session_driver = &local_nntp_session_driver;
152
153static inline struct nntp_session_state_data *
154get_data(mailsession * session)
155{
156 return session->sess_data;
157}
158
159static inline newsnntp * get_nntp_session(mailsession * session)
160{
161 return get_data(session)->nntp_session;
162}
163
164static int nntpdriver_initialize(mailsession * session)
165{
166 struct nntp_session_state_data * data;
167 newsnntp * nntp;
168
169 nntp = newsnntp_new(0, NULL);
170 if (nntp == NULL)
171 goto err;
172
173 data = malloc(sizeof(* data));
174 if (data == NULL)
175 goto free;
176
177 data->nntp_session = nntp;
178
179 data->nntp_userid = NULL;
180 data->nntp_password = NULL;
181
182 data->nntp_group_info = NULL;
183 data->nntp_group_name = NULL;
184
185 data->nntp_subscribed_list = clist_new();
186 if (data->nntp_subscribed_list == NULL)
187 goto free_data;
188
189 data->nntp_max_articles = 0;
190
191 data->nntp_mode_reader = FALSE;
192
193 session->sess_data = data;
194
195 return MAIL_NO_ERROR;
196
197 free_data:
198 free(data);
199 free:
200 newsnntp_free(nntp);
201 err:
202 return MAIL_ERROR_MEMORY;
203}
204
205static void nntpdriver_uninitialize(mailsession * session)
206{
207 struct nntp_session_state_data * data;
208
209 data = get_data(session);
210
211 clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL);
212 clist_free(data->nntp_subscribed_list);
213
214 if (data->nntp_group_info != NULL)
215 newsnntp_group_free(data->nntp_group_info);
216
217 if (data->nntp_group_name != NULL)
218 free(data->nntp_group_name);
219
220 if (data->nntp_userid != NULL)
221 free(data->nntp_userid);
222
223 if (data->nntp_password != NULL)
224 free(data->nntp_password);
225
226 newsnntp_free(data->nntp_session);
227 free(data);
228
229 session->sess_data = NULL;
230}
231
232
233static int nntpdriver_parameters(mailsession * session,
234 int id, void * value)
235{
236 struct nntp_session_state_data * data;
237
238 data = get_data(session);
239
240 switch (id) {
241 case NNTPDRIVER_SET_MAX_ARTICLES:
242 {
243 uint32_t * param;
244
245 param = value;
246
247 data->nntp_max_articles = * param;
248 return MAIL_NO_ERROR;
249 }
250 }
251
252 return MAIL_ERROR_INVAL;
253}
254
255
256static int add_to_list(mailsession * session, char * mb)
257{
258 char * new_mb;
259 int r;
260 struct nntp_session_state_data * data;
261
262 data = get_data(session);
263
264 new_mb = strdup(mb);
265 if (new_mb == NULL)
266 return -1;
267
268 r = clist_append(data->nntp_subscribed_list, new_mb);
269 if (r < 0) {
270 free(mb);
271 return -1;
272 }
273
274 return 0;
275}
276
277static int remove_from_list(mailsession * session, char * mb)
278{
279 clistiter * cur;
280 struct nntp_session_state_data * data;
281
282 data = get_data(session);
283
284 for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ;
285 cur = clist_next(cur)) {
286 char * cur_name;
287
288 cur_name = clist_content(cur);
289 if (strcmp(cur_name, mb) == 0) {
290 clist_delete(data->nntp_subscribed_list, cur);
291 free(cur_name);
292 return 0;
293 }
294 }
295
296 return -1;
297}
298
299
300static int nntpdriver_connect_stream(mailsession * session, mailstream * s)
301{
302 int r;
303
304 r = newsnntp_connect(get_nntp_session(session), s);
305
306 switch (r) {
307 case NEWSNNTP_NO_ERROR:
308 return MAIL_NO_ERROR_NON_AUTHENTICATED;
309
310 default:
311 return nntpdriver_nntp_error_to_mail_error(r);
312 }
313}
314
315static int nntpdriver_login(mailsession * session,
316 char * userid, char * password)
317{
318 struct nntp_session_state_data * data;
319 char * new_userid;
320 char * new_password;
321
322 data = get_data(session);
323
324 if (userid != NULL) {
325 new_userid = strdup(userid);
326 if (new_userid == NULL)
327 goto err;
328 }
329 else
330 new_userid = NULL;
331
332 if (password != NULL) {
333 new_password = strdup(password);
334 if (new_password == NULL)
335 goto free_uid;
336 }
337 else
338 new_password = NULL;
339
340 data->nntp_userid = new_userid;
341 data->nntp_password = new_password;
342
343 return MAIL_NO_ERROR;
344
345 free_uid:
346 if (new_userid != NULL)
347 free(new_userid);
348 err:
349 return MAIL_ERROR_MEMORY;
350}
351
352static int nntpdriver_logout(mailsession * session)
353{
354 int r;
355
356 r = newsnntp_quit(get_nntp_session(session));
357
358 return nntpdriver_nntp_error_to_mail_error(r);
359}
360
361
362static int nntpdriver_status_folder(mailsession * session, char * mb,
363 uint32_t * result_messages,
364 uint32_t * result_recent,
365 uint32_t * result_unseen)
366{
367 uint32_t count;
368 int r;
369
370 r = nntpdriver_select_folder(session, mb);
371 if (r != MAIL_NO_ERROR)
372 return r;
373
374 r = nntpdriver_messages_number(session, mb, &count);
375 if (r != MAIL_NO_ERROR)
376 return r;
377
378 * result_messages = count;
379 * result_recent = count;
380 * result_unseen = count;
381
382 return MAIL_NO_ERROR;
383}
384
385static int nntpdriver_messages_number(mailsession * session, char * mb,
386 uint32_t * result)
387{
388 int r;
389 struct nntp_session_state_data * data;
390
391 if (mb != NULL) {
392 r = nntpdriver_select_folder(session, mb);
393 if (r != MAIL_NO_ERROR)
394 return r;
395 }
396
397 data = get_data(session);
398
399 if (data->nntp_group_info == NULL)
400 return MAIL_ERROR_FOLDER_NOT_FOUND;
401
402 * result = data->nntp_group_info->grp_last -
403 data->nntp_group_info->grp_first + 1;
404
405 return MAIL_NO_ERROR;
406}
407
408static int nntpdriver_list_folders(mailsession * session, char * mb,
409 struct mail_list ** result)
410{
411 int r;
412 clist * group_list;
413 newsnntp * nntp;
414 clistiter * cur;
415 char * new_mb;
416 int done;
417 clist * list;
418 struct mail_list * ml;
419 int res;
420
421 nntp = get_nntp_session(session);
422
423 new_mb = NULL;
424 if ((mb != NULL) && (*mb != '\0')) {
425 new_mb = malloc(strlen(mb) + 3);
426 if (new_mb == NULL) {
427 res = MAIL_ERROR_MEMORY;
428 goto err;
429 }
430 strcpy(new_mb, mb);
431 strcat(new_mb, ".*");
432 }
433
434 done = FALSE;
435 do {
436 if (new_mb != NULL)
437 r = newsnntp_list_active(nntp, new_mb, &group_list);
438 else
439 r = newsnntp_list(nntp, &group_list);
440
441 switch (r) {
442 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
443 r = nntpdriver_authenticate_user(session);
444 if (r != MAIL_NO_ERROR) {
445 res = r;
446 goto err;
447 }
448 break;
449
450 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
451 r = nntpdriver_authenticate_password(session);
452 if (r != MAIL_NO_ERROR) {
453 res = r;
454 goto err;
455 }
456 break;
457
458 case NEWSNNTP_NO_ERROR:
459 if (new_mb != NULL)
460 free(new_mb);
461 done = TRUE;
462 break;
463
464 default:
465 if (new_mb != NULL)
466 free(new_mb);
467 return nntpdriver_nntp_error_to_mail_error(r);
468 }
469 }
470 while (!done);
471
472 list = clist_new();
473 if (list == NULL) {
474 res = MAIL_ERROR_MEMORY;
475 goto err;
476 }
477
478 for(cur = clist_begin(group_list) ; cur != NULL ;
479 cur = clist_next(cur)) {
480 struct newsnntp_group_info * info;
481 char * new_name;
482
483 info = clist_content(cur);
484 new_name = strdup(info->grp_name);
485 if (new_name == NULL) {
486 res = MAIL_ERROR_MEMORY;
487 goto free_list;
488 }
489
490 r = clist_append(list, new_name);
491 if (r < 0) {
492 free(new_name);
493 res = MAIL_ERROR_MEMORY;
494 goto free_list;
495 }
496 }
497
498 ml = mail_list_new(list);
499 if (ml == NULL) {
500 res = MAIL_ERROR_MEMORY;
501 goto free_list;
502 }
503
504 newsnntp_list_free(group_list);
505
506 * result = ml;
507
508 return MAIL_NO_ERROR;
509
510 free_list:
511 clist_foreach(list, (clist_func) free, NULL);
512 clist_free(list);
513 newsnntp_list_free(group_list);
514 err:
515 return res;
516}
517
518static int nntpdriver_lsub_folders(mailsession * session, char * mb,
519 struct mail_list ** result)
520{
521 clist * subscribed;
522 clist * lsub_result;
523 clistiter * cur;
524 struct mail_list * lsub;
525 size_t length;
526 int res;
527 int r;
528 struct nntp_session_state_data * data;
529
530 length = strlen(mb);
531
532 data = get_data(session);
533
534 subscribed = data->nntp_subscribed_list;
535 lsub_result = clist_new();
536 if (lsub_result == NULL) {
537 res = MAIL_ERROR_MEMORY;
538 goto err;
539 }
540
541 for(cur = clist_begin(subscribed) ; cur != NULL ;
542 cur = clist_next(cur)) {
543 char * cur_mb;
544 char * new_mb;
545
546 cur_mb = clist_content(cur);
547
548 if (strncmp(mb, cur_mb, length) == 0) {
549 new_mb = strdup(cur_mb);
550 if (new_mb == NULL) {
551 res = MAIL_ERROR_MEMORY;
552 goto free_list;
553 }
554
555 r = clist_append(lsub_result, new_mb);
556 if (r < 0) {
557 free(new_mb);
558 res = MAIL_ERROR_MEMORY;
559 goto free_list;
560 }
561 }
562 }
563
564 lsub = mail_list_new(lsub_result);
565 if (lsub == NULL) {
566 res = MAIL_ERROR_MEMORY;
567 goto free_list;
568 }
569
570 * result = lsub;
571
572 return MAIL_NO_ERROR;
573
574 free_list:
575 clist_foreach(lsub_result, (clist_func) free, NULL);
576 clist_free(lsub_result);
577 err:
578 return res;
579}
580
581static int nntpdriver_subscribe_folder(mailsession * session, char * mb)
582{
583 int r;
584
585 r = add_to_list(session, mb);
586 if (r < 0)
587 return MAIL_ERROR_SUBSCRIBE;
588
589 return MAIL_NO_ERROR;
590}
591
592static int nntpdriver_unsubscribe_folder(mailsession * session, char * mb)
593{
594 int r;
595
596 r = remove_from_list(session, mb);
597 if (r < 0)
598 return MAIL_ERROR_UNSUBSCRIBE;
599
600 return MAIL_NO_ERROR;
601}
602
603
604
605/* messages operations */
606
607static int nntpdriver_append_message(mailsession * session,
608 char * message, size_t size)
609{
610 int r;
611 struct nntp_session_state_data * data;
612
613 data = get_data(session);
614
615 do {
616 r = newsnntp_post(get_nntp_session(session), message, size);
617 switch (r) {
618 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
619 r = nntpdriver_authenticate_user(session);
620 if (r != MAIL_NO_ERROR)
621 return r;
622 break;
623
624 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
625 r = nntpdriver_authenticate_password(session);
626 if (r != MAIL_NO_ERROR)
627 return r;
628 break;
629
630 default:
631 return nntpdriver_nntp_error_to_mail_error(r);
632 }
633 }
634 while (1);
635}
636
637static int nntpdriver_append_message_flags(mailsession * session,
638 char * message, size_t size, struct mail_flags * flags)
639{
640 return nntpdriver_append_message(session, message, size);
641}
642
643
644static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
645 struct mailimf_fields ** result);
646
647
648static int
649nntpdriver_get_envelopes_list(mailsession * session,
650 struct mailmessage_list * env_list)
651{
652 newsnntp * nntp;
653 int r;
654 struct nntp_session_state_data * data;
655 clist * list;
656 int done;
657 clistiter * cur;
658 uint32_t first_seq;
659 unsigned int i;
660
661 nntp = get_nntp_session(session);
662
663 data = get_data(session);
664
665 if (data->nntp_group_info == NULL)
666 return MAIL_ERROR_BAD_STATE;
667
668 first_seq = data->nntp_group_info->grp_first;
669
670 if (carray_count(env_list->msg_tab) > 0) {
671 mailmessage * msg;
672
673 msg = carray_get(env_list->msg_tab, 0);
674
675 first_seq = msg->msg_index;
676 }
677
678 if (carray_count(env_list->msg_tab) > 0) {
679 i = carray_count(env_list->msg_tab) - 1;
680 while (1) {
681 mailmessage * msg;
682
683 msg = carray_get(env_list->msg_tab, i);
684
685 if (msg->msg_fields != NULL) {
686 first_seq = msg->msg_index + 1;
687 break;
688 }
689
690 if (i == 0)
691 break;
692
693 i --;
694 }
695 }
696
697 if (first_seq > data->nntp_group_info->grp_last) {
698 list = NULL;
699 }
700 else {
701 done = FALSE;
702 do {
703 r = newsnntp_xover_range(nntp, first_seq,
704 data->nntp_group_info->grp_last, &list);
705
706 switch (r) {
707 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
708 r = nntpdriver_authenticate_user(session);
709 if (r != MAIL_NO_ERROR)
710 return r;
711 break;
712
713 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
714 r = nntpdriver_authenticate_password(session);
715 if (r != MAIL_NO_ERROR)
716 return r;
717 break;
718
719 case NEWSNNTP_NO_ERROR:
720 done = TRUE;
721 break;
722
723 default:
724 return nntpdriver_nntp_error_to_mail_error(r);
725 }
726 }
727 while (!done);
728 }
729
730#if 0
731 i = 0;
732 j = 0;
733
734 if (list != NULL) {
735 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
736 struct newsnntp_xover_resp_item * item;
737 struct mailimf_fields * fields;
738
739 item = clist_content(cur);
740
741 while (i < carray_count(env_list->msg_tab)) {
742 mailmessage * info;
743
744 info = carray_get(env_list->msg_tab, i);
745
746 if (item->ovr_article == info->msg_index) {
747
748 if (info->fields == NULL) {
749 r = xover_resp_to_fields(item, &fields);
750 if (r == MAIL_NO_ERROR) {
751 info->fields = fields;
752 }
753
754 info->size = item->ovr_size;
755
756 carray_set(env_list->msg_tab, j, info);
757 j ++;
758 i ++;
759 break;
760 }
761 else {
762 carray_set(env_list->msg_tab, j, info);
763 j ++;
764 }
765 }
766 else {
767 if (info->fields != NULL) {
768 carray_set(env_list->msg_tab, j, info);
769 j ++;
770 }
771 else {
772 if (info->flags != NULL) {
773 info->flags->flags &= ~MAIL_FLAG_NEW;
774 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
775 mailmessage_check(info);
776 }
777 mailmessage_free(info);
778 carray_set(env_list->msg_tab, i, NULL);
779 }
780 }
781
782 i ++;
783 }
784 }
785 }
786
787 while (i < carray_count(env_list->msg_tab)) {
788 mailmessage * info;
789
790 info = carray_get(env_list->msg_tab, i);
791 if (info->fields != NULL) {
792 carray_set(env_list->msg_tab, j, info);
793 j ++;
794 }
795 else {
796 if (info->flags != NULL) {
797 info->flags->flags &= ~MAIL_FLAG_NEW;
798 info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED;
799 mailmessage_check(info);
800 }
801 mailmessage_free(info);
802 carray_set(env_list->msg_tab, i, NULL);
803 }
804
805 i ++;
806 }
807
808 r = carray_set_size(env_list->msg_tab, j);
809 if (r < 0) {
810 if (list != NULL)
811 newsnntp_xover_resp_list_free(list);
812 return MAIL_ERROR_MEMORY;
813 }
814#endif
815 i = 0;
816
817 if (list != NULL) {
818 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
819 struct newsnntp_xover_resp_item * item;
820 struct mailimf_fields * fields;
821
822 item = clist_content(cur);
823
824 while (i < carray_count(env_list->msg_tab)) {
825 mailmessage * info;
826
827 info = carray_get(env_list->msg_tab, i);
828
829 if (item->ovr_article == info->msg_index) {
830
831 if (info->msg_fields == NULL) {
832 r = xover_resp_to_fields(item, &fields);
833 if (r == MAIL_NO_ERROR) {
834 info->msg_fields = fields;
835 }
836
837 info->msg_size = item->ovr_size;
838
839 i ++;
840 break;
841 }
842 }
843#if 0
844 else if ((info->fields == NULL) && (info->flags != NULL)) {
845 info->flags->flags &= ~MAIL_FLAG_NEW;
846 info->flags->flags |= MAIL_FLAG_CANCELLED;
847 mailmessage_check(info);
848 }
849#endif
850
851 i ++;
852 }
853 }
854 }
855
856#if 0
857 while (i < env_list->msg_tab->len) {
858 mailmessage * info;
859
860 info = carray_get(env_list->msg_tab, i);
861 if ((info->fields == NULL) && (info->flags != NULL)) {
862 info->flags->flags &= ~MAIL_FLAG_NEW;
863 info->flags->flags |= MAIL_FLAG_CANCELLED;
864 mailmessage_check(info);
865 }
866
867 i ++;
868 }
869#endif
870
871 if (list != NULL)
872 newsnntp_xover_resp_list_free(list);
873
874 return MAIL_NO_ERROR;
875}
876
877
878static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item,
879 struct mailimf_fields ** result)
880{
881 size_t cur_token;
882 clist * list;
883 int r;
884 struct mailimf_fields * fields;
885 int res;
886
887 list = clist_new();
888 if (list == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto err;
891 }
892
893 if (item->ovr_subject != NULL) {
894 char * subject_str;
895 struct mailimf_subject * subject;
896 struct mailimf_field * field;
897
898 subject_str = strdup(item->ovr_subject);
899 if (subject_str == NULL) {
900 res = MAIL_ERROR_MEMORY;
901 goto free_list;
902 }
903
904 subject = mailimf_subject_new(subject_str);
905 if (subject == NULL) {
906 free(subject_str);
907 res = MAIL_ERROR_MEMORY;
908 goto free_list;
909 }
910
911 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
912 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
913 NULL, NULL, NULL,
914 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
915 NULL, subject, NULL, NULL, NULL);
916 if (field == NULL) {
917 mailimf_subject_free(subject);
918 res = MAIL_ERROR_MEMORY;
919 goto free_list;
920 }
921
922 r = clist_append(list, field);
923 if (r < 0) {
924 mailimf_field_free(field);
925 res = MAIL_ERROR_MEMORY;
926 goto free_list;
927 }
928 }
929
930 if (item->ovr_author != NULL) {
931 struct mailimf_mailbox_list * mb_list;
932 struct mailimf_from * from;
933 struct mailimf_field * field;
934
935 cur_token = 0;
936 r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author),
937 &cur_token, &mb_list);
938 switch (r) {
939 case MAILIMF_NO_ERROR:
940 from = mailimf_from_new(mb_list);
941 if (from == NULL) {
942 mailimf_mailbox_list_free(mb_list);
943 res = MAIL_ERROR_MEMORY;
944 goto free_list;
945 }
946
947 field = mailimf_field_new(MAILIMF_FIELD_FROM,
948 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
949 NULL, NULL, from,
950 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
951 NULL, NULL, NULL, NULL, NULL);
952 if (field == NULL) {
953 mailimf_from_free(from);
954 res = MAIL_ERROR_MEMORY;
955 goto free_list;
956 }
957
958 r = clist_append(list, field);
959 if (r < 0) {
960 mailimf_field_free(field);
961 res = MAIL_ERROR_MEMORY;
962 goto free_list;
963 }
964 break;
965
966 case MAILIMF_ERROR_PARSE:
967 break;
968
969 default:
970 res = maildriver_imf_error_to_mail_error(r);
971 goto free_list;
972 }
973 }
974
975 if (item->ovr_date != NULL) {
976 struct mailimf_date_time * date_time;
977 struct mailimf_orig_date * orig_date;
978 struct mailimf_field * field;
979
980 cur_token = 0;
981 r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date),
982 &cur_token, &date_time);
983 switch (r) {
984 case MAILIMF_NO_ERROR:
985 orig_date = mailimf_orig_date_new(date_time);
986 if (orig_date == NULL) {
987 mailimf_date_time_free(date_time);
988 res = MAIL_ERROR_MEMORY;
989 goto free_list;
990 }
991
992 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
993 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
994 NULL, orig_date, NULL,
995 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
996 NULL, NULL, NULL, NULL, NULL);
997 if (field == NULL) {
998 mailimf_orig_date_free(orig_date);
999 res = MAIL_ERROR_MEMORY;
1000 goto free_list;
1001 }
1002
1003 r = clist_append(list, field);
1004 if (r < 0) {
1005 mailimf_field_free(field);
1006 res = MAIL_ERROR_MEMORY;
1007 goto free_list;
1008 }
1009 break;
1010
1011 case MAILIMF_ERROR_PARSE:
1012 break;
1013
1014 default:
1015 res = maildriver_imf_error_to_mail_error(r);
1016 goto free_list;
1017 }
1018 }
1019
1020 if (item->ovr_message_id != NULL) {
1021 char * msgid_str;
1022 struct mailimf_message_id * msgid;
1023 struct mailimf_field * field;
1024
1025 cur_token = 0;
1026 r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id),
1027 &cur_token, &msgid_str);
1028
1029 switch (r) {
1030 case MAILIMF_NO_ERROR:
1031 msgid = mailimf_message_id_new(msgid_str);
1032 if (msgid == NULL) {
1033 mailimf_msg_id_free(msgid_str);
1034 res = MAIL_ERROR_MEMORY;
1035 goto free_list;
1036 }
1037
1038 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1039 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1040 NULL, NULL, NULL,
1041 NULL, NULL, NULL, NULL, NULL, msgid, NULL,
1042 NULL, NULL, NULL, NULL, NULL);
1043
1044 r = clist_append(list, field);
1045 if (r < 0) {
1046 mailimf_field_free(field);
1047 res = MAIL_ERROR_MEMORY;
1048 goto free_list;
1049 }
1050 break;
1051
1052 case MAILIMF_ERROR_PARSE:
1053 break;
1054
1055 default:
1056 res = maildriver_imf_error_to_mail_error(r);
1057 goto free_list;
1058 }
1059 }
1060
1061 if (item->ovr_references != NULL) {
1062 clist * msgid_list;
1063 struct mailimf_references * references;
1064 struct mailimf_field * field;
1065
1066 cur_token = 0;
1067
1068 r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references),
1069 &cur_token, &msgid_list);
1070
1071 switch (r) {
1072 case MAILIMF_NO_ERROR:
1073 references = mailimf_references_new(msgid_list);
1074 if (references == NULL) {
1075 clist_foreach(msgid_list,
1076 (clist_func) mailimf_msg_id_free, NULL);
1077 clist_free(msgid_list);
1078 res = MAIL_ERROR_MEMORY;
1079 goto free_list;
1080 }
1081
1082 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1083 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1084 NULL, NULL, NULL,
1085 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1086 references, NULL, NULL, NULL, NULL);
1087
1088 r = clist_append(list, field);
1089 if (r < 0) {
1090 mailimf_field_free(field);
1091 res = MAIL_ERROR_MEMORY;
1092 goto free_list;
1093 }
1094
1095 case MAILIMF_ERROR_PARSE:
1096 break;
1097
1098 default:
1099 res = maildriver_imf_error_to_mail_error(r);
1100 goto free_list;
1101 }
1102 }
1103
1104 fields = mailimf_fields_new(list);
1105 if (fields == NULL) {
1106 res = MAIL_ERROR_MEMORY;
1107 goto free_list;
1108 }
1109
1110 * result = fields;
1111
1112 return MAIL_NO_ERROR;
1113
1114 free_list:
1115 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
1116 clist_free(list);
1117 err:
1118 return res;
1119}
1120
1121
1122/* get messages list with group info */
1123
1124static int nntpdriver_get_messages_list(mailsession * session,
1125 struct mailmessage_list ** result)
1126{
1127 return nntp_get_messages_list(session, session, nntp_message_driver, result);
1128
1129}
1130
1131static int nntpdriver_get_message(mailsession * session,
1132 uint32_t num, mailmessage ** result)
1133{
1134 mailmessage * msg_info;
1135 int r;
1136
1137 msg_info = mailmessage_new();
1138 if (msg_info == NULL)
1139 return MAIL_ERROR_MEMORY;
1140
1141 r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0);
1142 if (r != MAIL_NO_ERROR) {
1143 mailmessage_free(msg_info);
1144 return r;
1145 }
1146
1147 * result = msg_info;
1148
1149 return MAIL_NO_ERROR;
1150}
1151
1152static int nntpdriver_noop(mailsession * session)
1153{
1154 newsnntp * nntp;
1155 int r;
1156 struct tm tm;
1157
1158 nntp = get_nntp_session(session);
1159
1160 r = newsnntp_date(nntp, &tm);
1161
1162 return nntpdriver_nntp_error_to_mail_error(r);
1163}
1164
1165static int nntpdriver_get_message_by_uid(mailsession * session,
1166 const char * uid,
1167 mailmessage ** result)
1168{
1169 uint32_t num;
1170 char * p;
1171
1172 if (uid == NULL)
1173 return MAIL_ERROR_INVAL;
1174
1175 num = strtoul(uid, &p, 10);
1176 if ((p == uid) || (* p != '\0'))
1177 return MAIL_ERROR_INVAL;
1178
1179 return nntpdriver_get_message(session, num, result);
1180 }
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver.h b/libetpan/src/driver/implementation/nntp/nntpdriver.h
new file mode 100644
index 0000000..56aaa39
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_H
37
38#define NNTPDRIVER_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
new file mode 100644
index 0000000..5c29b7b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c
@@ -0,0 +1,1059 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <string.h>
41#include <stdio.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail_cache_db.h"
49
50#include "mail.h"
51#include "mailmessage.h"
52#include "maildriver_tools.h"
53#include "nntpdriver.h"
54#include "maildriver.h"
55#include "newsnntp.h"
56#include "generic_cache.h"
57#include "imfcache.h"
58#include "maillock.h"
59#include "nntpdriver_cached_message.h"
60#include "nntpdriver_tools.h"
61
62static int nntpdriver_cached_initialize(mailsession * session);
63
64static void nntpdriver_cached_uninitialize(mailsession * session);
65
66static int nntpdriver_cached_parameters(mailsession * session,
67 int id, void * value);
68
69static int nntpdriver_cached_connect_stream(mailsession * session,
70 mailstream * s);
71
72static int nntpdriver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int nntpdriver_cached_logout(mailsession * session);
76
77static int nntpdriver_cached_check_folder(mailsession * session);
78
79static int nntpdriver_cached_select_folder(mailsession * session, char * mb);
80
81static int nntpdriver_cached_status_folder(mailsession * session,
82 char * mb,
83 uint32_t * result_messages,
84 uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int nntpdriver_cached_messages_number(mailsession * session, char * mb,
88 uint32_t * result);
89
90static int nntpdriver_cached_recent_number(mailsession * session, char * mb,
91 uint32_t * result);
92
93static int nntpdriver_cached_unseen_number(mailsession * session, char * mb,
94 uint32_t * result);
95
96static int nntpdriver_cached_append_message(mailsession * session,
97 char * message, size_t size);
98
99static int nntpdriver_cached_append_message_flags(mailsession * session,
100 char * message, size_t size, struct mail_flags * flags);
101
102static int
103nntpdriver_cached_get_envelopes_list(mailsession * session,
104 struct mailmessage_list * env_list);
105
106
107static int
108nntpdriver_cached_get_messages_list(mailsession * session,
109 struct mailmessage_list ** result);
110
111static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
112 struct mail_list ** result);
113
114static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
115 struct mail_list ** result);
116
117static int nntpdriver_cached_subscribe_folder(mailsession * session,
118 char * mb);
119
120static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
121 char * mb);
122
123static int nntpdriver_cached_get_message(mailsession * session,
124 uint32_t num, mailmessage ** result);
125
126static int nntpdriver_cached_noop(mailsession * session);
127
128static int nntpdriver_cached_get_message_by_uid(mailsession * session,
129 const char * uid,
130 mailmessage ** result);
131
132static mailsession_driver local_nntp_cached_session_driver = {
133 .sess_name = "nntp-cached",
134
135 .sess_initialize = nntpdriver_cached_initialize,
136 .sess_uninitialize = nntpdriver_cached_uninitialize,
137
138 .sess_parameters = nntpdriver_cached_parameters,
139
140 .sess_connect_stream = nntpdriver_cached_connect_stream,
141 .sess_connect_path = NULL,
142 .sess_starttls = NULL,
143 .sess_login = nntpdriver_cached_login,
144 .sess_logout = nntpdriver_cached_logout,
145 .sess_noop = nntpdriver_cached_noop,
146
147 .sess_build_folder_name = NULL,
148 .sess_create_folder = NULL,
149 .sess_delete_folder = NULL,
150 .sess_rename_folder = NULL,
151 .sess_check_folder = nntpdriver_cached_check_folder,
152 .sess_examine_folder = NULL,
153 .sess_select_folder = nntpdriver_cached_select_folder,
154 .sess_expunge_folder = NULL,
155 .sess_status_folder = nntpdriver_cached_status_folder,
156 .sess_messages_number = nntpdriver_cached_messages_number,
157 .sess_recent_number = nntpdriver_cached_recent_number,
158 .sess_unseen_number = nntpdriver_cached_unseen_number,
159 .sess_list_folders = nntpdriver_cached_list_folders,
160 .sess_lsub_folders = nntpdriver_cached_lsub_folders,
161 .sess_subscribe_folder = nntpdriver_cached_subscribe_folder,
162 .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder,
163
164 .sess_append_message = nntpdriver_cached_append_message,
165 .sess_append_message_flags = nntpdriver_cached_append_message_flags,
166 .sess_copy_message = NULL,
167 .sess_move_message = NULL,
168
169 .sess_get_messages_list = nntpdriver_cached_get_messages_list,
170 .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list,
171 .sess_remove_message = NULL,
172#if 0
173 .sess_search_messages = maildriver_generic_search_messages,
174#endif
175
176 .sess_get_message = nntpdriver_cached_get_message,
177 .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid,
178};
179
180
181mailsession_driver * nntp_cached_session_driver =
182&local_nntp_cached_session_driver;
183
184#define ENV_NAME "env.db"
185#define FLAGS_NAME "flags.db"
186
187
188
189static void read_article_seq(mailsession * session,
190 uint32_t * pfirst, uint32_t * plast);
191
192static void write_article_seq(mailsession * session,
193 uint32_t first, uint32_t last);
194
195
196static inline struct nntp_cached_session_state_data *
197get_cached_data(mailsession * session)
198{
199 return session->sess_data;
200}
201
202static inline mailsession * get_ancestor(mailsession * session)
203{
204 return get_cached_data(session)->nntp_ancestor;
205}
206
207static inline struct nntp_session_state_data *
208get_ancestor_data(mailsession * session)
209{
210 return get_ancestor(session)->sess_data;
211}
212
213static inline newsnntp * get_nntp_session(mailsession * session)
214{
215 return get_ancestor_data(session)->nntp_session;
216}
217
218static int nntpdriver_cached_initialize(mailsession * session)
219{
220 struct nntp_cached_session_state_data * data;
221
222 data = malloc(sizeof(* data));
223 if (data == NULL)
224 goto err;
225
226 data->nntp_flags_store = mail_flags_store_new();
227 if (data->nntp_flags_store == NULL)
228 goto free;
229
230 data->nntp_ancestor = mailsession_new(nntp_session_driver);
231 if (data->nntp_ancestor == NULL)
232 goto free_store;
233
234 session->sess_data = data;
235
236 return MAIL_NO_ERROR;
237
238 free_store:
239 mail_flags_store_free(data->nntp_flags_store);
240 free:
241 free(data);
242 err:
243 return MAIL_ERROR_MEMORY;
244}
245
246static int nntp_flags_store_process(char * flags_directory, char * group_name,
247 struct mail_flags_store * flags_store)
248{
249 char filename_flags[PATH_MAX];
250 struct mail_cache_db * cache_db_flags;
251 MMAPString * mmapstr;
252 unsigned int i;
253 int r;
254 int res;
255
256 if (carray_count(flags_store->fls_tab) == 0)
257 return MAIL_NO_ERROR;
258
259 if (group_name == NULL)
260 return MAIL_NO_ERROR;
261
262 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
263 flags_directory, group_name, FLAGS_NAME);
264
265 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
266 if (r < 0) {
267 res = MAIL_ERROR_FILE;
268 goto err;
269 }
270
271 mmapstr = mmap_string_new("");
272 if (mmapstr == NULL) {
273 res = MAIL_ERROR_MEMORY;
274 goto close_db_flags;
275 }
276
277 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
278 mailmessage * msg;
279
280 msg = carray_get(flags_store->fls_tab, i);
281
282 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
283 msg->msg_index, msg->msg_flags);
284 }
285
286 mmap_string_free(mmapstr);
287 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
288
289 mail_flags_store_clear(flags_store);
290
291 return MAIL_NO_ERROR;
292
293 close_db_flags:
294 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
295 err:
296 return res;
297}
298
299static void nntpdriver_cached_uninitialize(mailsession * session)
300{
301 struct nntp_cached_session_state_data * cached_data;
302 struct nntp_session_state_data * ancestor_data;
303
304 cached_data = get_cached_data(session);
305 ancestor_data = get_ancestor_data(session);
306
307 nntp_flags_store_process(cached_data->nntp_flags_directory,
308 ancestor_data->nntp_group_name,
309 cached_data->nntp_flags_store);
310
311 mail_flags_store_free(cached_data->nntp_flags_store);
312
313 mailsession_free(cached_data->nntp_ancestor);
314 free(cached_data);
315
316 session->sess_data = NULL;
317}
318
319static int nntpdriver_cached_parameters(mailsession * session,
320 int id, void * value)
321{
322 struct nntp_cached_session_state_data * cached_data;
323 int r;
324
325 cached_data = get_cached_data(session);
326
327 switch (id) {
328 case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY:
329 strncpy(cached_data->nntp_cache_directory, value, PATH_MAX);
330 cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0';
331
332 r = generic_cache_create_dir(cached_data->nntp_cache_directory);
333 if (r != MAIL_NO_ERROR)
334 return r;
335
336 return MAIL_NO_ERROR;
337
338 case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY:
339 strncpy(cached_data->nntp_flags_directory, value, PATH_MAX);
340 cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0';
341
342 r = generic_cache_create_dir(cached_data->nntp_flags_directory);
343 if (r != MAIL_NO_ERROR)
344 return r;
345
346 return MAIL_NO_ERROR;
347
348 default:
349 return mailsession_parameters(get_ancestor(session), id, value);
350 }
351}
352
353static int nntpdriver_cached_connect_stream(mailsession * session,
354 mailstream * s)
355{
356 return mailsession_connect_stream(get_ancestor(session), s);
357}
358
359static int nntpdriver_cached_login(mailsession * session,
360 char * userid, char * password)
361{
362 return mailsession_login(get_ancestor(session), userid, password);
363}
364
365static int nntpdriver_cached_logout(mailsession * session)
366{
367 struct nntp_cached_session_state_data * cached_data;
368 struct nntp_session_state_data * ancestor_data;
369
370 cached_data = get_cached_data(session);
371 ancestor_data = get_ancestor_data(session);
372
373 nntp_flags_store_process(cached_data->nntp_flags_directory,
374 ancestor_data->nntp_group_name,
375 cached_data->nntp_flags_store);
376
377 return mailsession_logout(get_ancestor(session));
378}
379
380static int nntpdriver_cached_select_folder(mailsession * session, char * mb)
381{
382 int r;
383 struct nntp_session_state_data * ancestor_data;
384 struct nntp_cached_session_state_data * cached_data;
385 int res;
386 char key[PATH_MAX];
387
388 cached_data = get_cached_data(session);
389 ancestor_data = get_ancestor_data(session);
390
391 nntp_flags_store_process(cached_data->nntp_flags_directory,
392 ancestor_data->nntp_group_name,
393 cached_data->nntp_flags_store);
394
395 r = mailsession_select_folder(get_ancestor(session), mb);
396 if (r != MAIL_NO_ERROR)
397 return r;
398
399 if (ancestor_data->nntp_group_name == NULL)
400 return MAIL_ERROR_BAD_STATE;
401
402 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory,
403 ancestor_data->nntp_group_name);
404
405 r = generic_cache_create_dir(key);
406 if (r != MAIL_NO_ERROR) {
407 res = r;
408 goto err;
409 }
410
411 snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory,
412 ancestor_data->nntp_group_name);
413
414 r = generic_cache_create_dir(key);
415 if (r != MAIL_NO_ERROR) {
416 res = r;
417 goto err;
418 }
419
420 return MAIL_NO_ERROR;
421
422 err:
423 return res;
424}
425
426static int nntpdriver_cached_check_folder(mailsession * session)
427{
428 struct nntp_session_state_data * ancestor_data;
429 struct nntp_cached_session_state_data * cached_data;
430
431 cached_data = get_cached_data(session);
432 ancestor_data = get_ancestor_data(session);
433
434 nntp_flags_store_process(cached_data->nntp_flags_directory,
435 ancestor_data->nntp_group_name,
436 cached_data->nntp_flags_store);
437
438 return MAIL_NO_ERROR;
439}
440
441
442static int nntpdriver_cached_status_folder(mailsession * session,
443 char * mb, uint32_t * result_messages, uint32_t * result_recent,
444 uint32_t * result_unseen)
445{
446 int res;
447 struct nntp_cached_session_state_data * cached_data;
448 struct nntp_session_state_data * ancestor_data;
449 char filename_flags[PATH_MAX];
450 struct mail_cache_db * cache_db_flags;
451 MMAPString * mmapstr;
452 uint32_t i;
453 int r;
454 uint32_t recent;
455 uint32_t unseen;
456 uint32_t first;
457 uint32_t last;
458 uint32_t count;
459 uint32_t additionnal;
460
461 r = nntpdriver_cached_select_folder(session, mb);
462 if (r != MAIL_NO_ERROR) {
463 res = r;
464 goto err;
465 }
466
467 read_article_seq(session, &first, &last);
468
469 count = 0;
470 recent = 0;
471 unseen = 0;
472
473 ancestor_data = get_ancestor_data(session);
474 cached_data = get_cached_data(session);
475 if (ancestor_data->nntp_group_name == NULL) {
476 res = MAIL_ERROR_BAD_STATE;
477 goto err;
478 }
479
480 if (ancestor_data->nntp_group_info->grp_first > first)
481 first = ancestor_data->nntp_group_info->grp_first;
482 if (last < first)
483 last = ancestor_data->nntp_group_info->grp_last;
484
485 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
486 cached_data->nntp_flags_directory,
487 ancestor_data->nntp_group_name, FLAGS_NAME);
488
489 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
490 if (r < 0) {
491 res = MAIL_ERROR_MEMORY;
492 goto err;
493 }
494
495 mmapstr = mmap_string_new("");
496 if (mmapstr == NULL) {
497 res = MAIL_ERROR_MEMORY;
498 goto close_db_flags;
499 }
500
501 for(i = first ; i <= last ; i++) {
502 struct mail_flags * flags;
503
504 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
505 i, &flags);
506 if (r == MAIL_NO_ERROR) {
507 if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) {
508 mail_flags_free(flags);
509 continue;
510 }
511
512 count ++;
513 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
514 recent ++;
515 }
516 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
517 unseen ++;
518 }
519 mail_flags_free(flags);
520 }
521 }
522
523 if ((count == 0) && (first != last)) {
524 count = last - first + 1;
525 recent = count;
526 unseen = count;
527 }
528
529 additionnal = ancestor_data->nntp_group_info->grp_last - last;
530 recent += additionnal;
531 unseen += additionnal;
532
533 mmap_string_free(mmapstr);
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535
536 * result_messages = count;
537 * result_recent = recent;
538 * result_unseen = unseen;
539
540 return MAIL_NO_ERROR;
541
542 close_db_flags:
543 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
544 err:
545 return res;
546}
547
548static int nntpdriver_cached_messages_number(mailsession * session,
549 char * mb,
550 uint32_t * result)
551{
552 uint32_t messages;
553 uint32_t recent;
554 uint32_t unseen;
555 int r;
556
557 r = nntpdriver_cached_status_folder(session, mb,
558 &messages, &recent, &unseen);
559 if (r != MAIL_NO_ERROR)
560 return r;
561
562 * result = messages;
563
564 return MAIL_NO_ERROR;
565}
566
567static int nntpdriver_cached_recent_number(mailsession * session,
568 char * mb,
569 uint32_t * result)
570{
571 uint32_t messages;
572 uint32_t recent;
573 uint32_t unseen;
574 int r;
575
576 r = nntpdriver_cached_status_folder(session, mb,
577 &messages, &recent, &unseen);
578 if (r != MAIL_NO_ERROR)
579 return r;
580
581 * result = recent;
582
583 return MAIL_NO_ERROR;
584}
585
586static int nntpdriver_cached_unseen_number(mailsession * session,
587 char * mb,
588 uint32_t * result)
589{
590 uint32_t messages;
591 uint32_t recent;
592 uint32_t unseen;
593 int r;
594
595 r = nntpdriver_cached_status_folder(session, mb,
596 &messages, &recent, &unseen);
597 if (r != MAIL_NO_ERROR)
598 return r;
599
600 * result = unseen;
601
602 return MAIL_NO_ERROR;
603}
604
605static int nntpdriver_cached_list_folders(mailsession * session, char * mb,
606 struct mail_list ** result)
607{
608 return mailsession_list_folders(get_ancestor(session), mb, result);
609}
610
611static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb,
612 struct mail_list ** result)
613{
614 return mailsession_lsub_folders(get_ancestor(session), mb, result);
615}
616
617static int nntpdriver_cached_subscribe_folder(mailsession * session,
618 char * mb)
619{
620 return mailsession_subscribe_folder(get_ancestor(session), mb);
621}
622
623static int nntpdriver_cached_unsubscribe_folder(mailsession * session,
624 char * mb)
625{
626 return mailsession_unsubscribe_folder(get_ancestor(session), mb);
627}
628
629
630
631/* messages operations */
632
633static int nntpdriver_cached_append_message(mailsession * session,
634 char * message, size_t size)
635{
636 return mailsession_append_message(get_ancestor(session), message, size);
637}
638
639static int nntpdriver_cached_append_message_flags(mailsession * session,
640 char * message, size_t size, struct mail_flags * flags)
641{
642 return nntpdriver_cached_append_message(session, message, size);
643}
644
645
646
647static int
648get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
649 mailsession * session, uint32_t num,
650 struct mailimf_fields ** result)
651{
652 char keyname[PATH_MAX];
653 int r;
654 struct mailimf_fields * fields;
655 int res;
656
657 snprintf(keyname, PATH_MAX, "%i-envelope", num);
658
659 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
660 if (r != MAIL_NO_ERROR) {
661 res = r;
662 goto err;
663 }
664
665 * result = fields;
666
667 return MAIL_NO_ERROR;
668
669 err:
670 return res;
671}
672
673static int
674write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
675 mailsession * session, uint32_t num,
676 struct mailimf_fields * fields)
677{
678 int r;
679 int res;
680 char keyname[PATH_MAX];
681
682 snprintf(keyname, PATH_MAX, "%i-envelope", num);
683
684 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
685 if (r != MAIL_NO_ERROR) {
686 res = r;
687 goto err;
688 }
689
690 return MAIL_NO_ERROR;
691
692 err:
693 return res;
694}
695
696#define SEQ_FILENAME "articles-seq"
697
698static void read_article_seq(mailsession * session,
699 uint32_t * pfirst, uint32_t * plast)
700{
701 FILE * f;
702 struct nntp_session_state_data * ancestor_data;
703 uint32_t first;
704 uint32_t last;
705 char seq_filename[PATH_MAX];
706 struct nntp_cached_session_state_data * cached_data;
707 int r;
708
709 first = 0;
710 last = 0;
711
712 cached_data = get_cached_data(session);
713 ancestor_data = get_ancestor_data(session);
714
715 if (ancestor_data->nntp_group_name == NULL)
716 return;
717
718 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
719 cached_data->nntp_cache_directory,
720 ancestor_data->nntp_group_name, SEQ_FILENAME);
721 f = fopen(seq_filename, "r");
722
723 if (f != NULL) {
724 int fd;
725
726 fd = fileno(f);
727
728 r = maillock_read_lock(seq_filename, fd);
729 if (r == 0) {
730 MMAPString * mmapstr;
731 size_t cur_token;
732 char buf[sizeof(uint32_t) * 2];
733 size_t read_size;
734
735 read_size = fread(buf, 1, sizeof(uint32_t) * 2, f);
736 mmapstr = mmap_string_new_len(buf, read_size);
737 if (mmapstr != NULL) {
738 cur_token = 0;
739 r = mailimf_cache_int_read(mmapstr, &cur_token, &first);
740 r = mailimf_cache_int_read(mmapstr, &cur_token, &last);
741
742 mmap_string_free(mmapstr);
743 }
744
745 maillock_read_unlock(seq_filename, fd);
746 }
747 fclose(f);
748 }
749
750 * pfirst = first;
751 * plast = last;
752}
753
754static void write_article_seq(mailsession * session,
755 uint32_t first, uint32_t last)
756{
757 FILE * f;
758 struct nntp_session_state_data * ancestor_data;
759 char seq_filename[PATH_MAX];
760 struct nntp_cached_session_state_data * cached_data;
761 int r;
762 int fd;
763
764 cached_data = get_cached_data(session);
765 ancestor_data = get_ancestor_data(session);
766
767 if (ancestor_data->nntp_group_name == NULL)
768 return;
769
770 snprintf(seq_filename, PATH_MAX, "%s/%s/%s",
771 cached_data->nntp_cache_directory,
772 ancestor_data->nntp_group_name, SEQ_FILENAME);
773
774 fd = creat(seq_filename, S_IRUSR | S_IWUSR);
775 if (fd < 0)
776 return;
777
778 f = fdopen(fd, "w");
779 if (f != NULL) {
780 r = maillock_write_lock(seq_filename, fd);
781 if (r == 0) {
782 MMAPString * mmapstr;
783 size_t cur_token;
784
785 mmapstr = mmap_string_new("");
786 if (mmapstr != NULL) {
787 r = mail_serialize_clear(mmapstr, &cur_token);
788 if (r == MAIL_NO_ERROR) {
789 r = mailimf_cache_int_write(mmapstr, &cur_token, first);
790 r = mailimf_cache_int_write(mmapstr, &cur_token, last);
791
792 fwrite(mmapstr->str, 1, mmapstr->len, f);
793 }
794
795 mmap_string_free(mmapstr);
796 }
797
798 maillock_write_unlock(seq_filename, fd);
799 }
800 fclose(f);
801 }
802 else
803 close(fd);
804}
805
806
807static void get_uid_from_filename(char * filename)
808{
809 char * p;
810
811 if (strcmp(filename, SEQ_FILENAME) == 0)
812 * filename = 0;
813
814 p = strstr(filename, "-header");
815 if (p != NULL)
816 * p = 0;
817}
818
819static int
820nntpdriver_cached_get_envelopes_list(mailsession * session,
821 struct mailmessage_list * env_list)
822{
823 int r;
824 unsigned int i;
825 struct nntp_cached_session_state_data * cached_data;
826 uint32_t first;
827 uint32_t last;
828 struct nntp_session_state_data * ancestor_data;
829 char filename_env[PATH_MAX];
830 char filename_flags[PATH_MAX];
831 struct mail_cache_db * cache_db_env;
832 struct mail_cache_db * cache_db_flags;
833 MMAPString * mmapstr;
834 int res;
835 char cache_dir[PATH_MAX];
836
837 cached_data = get_cached_data(session);
838 ancestor_data = get_ancestor_data(session);
839
840 nntp_flags_store_process(cached_data->nntp_flags_directory,
841 ancestor_data->nntp_group_name,
842 cached_data->nntp_flags_store);
843
844 if (ancestor_data->nntp_group_name == NULL) {
845 res = MAIL_ERROR_BAD_STATE;
846 goto err;
847 }
848
849 /* read articles sequence */
850
851 read_article_seq(session, &first, &last);
852
853 mmapstr = mmap_string_new("");
854 if (mmapstr == NULL) {
855 res = MAIL_ERROR_MEMORY;
856 goto err;
857 }
858
859 snprintf(filename_env, PATH_MAX, "%s/%s/%s",
860 cached_data->nntp_cache_directory,
861 ancestor_data->nntp_group_name, ENV_NAME);
862
863 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
864 if (r < 0) {
865 res = MAIL_ERROR_MEMORY;
866 goto free_mmapstr;
867 }
868
869 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
870 cached_data->nntp_flags_directory,
871 ancestor_data->nntp_group_name, FLAGS_NAME);
872
873 /* fill with cached */
874
875 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
876 mailmessage * msg;
877 struct mailimf_fields * fields;
878
879 msg = carray_get(env_list->msg_tab, i);
880
881 if ((msg->msg_index < first) || (msg->msg_index > last))
882 continue;
883
884 if (msg->msg_fields == NULL) {
885 r = get_cached_envelope(cache_db_env, mmapstr,
886 session, msg->msg_index, &fields);
887 if (r == MAIL_NO_ERROR) {
888 msg->msg_fields = fields;
889 msg->msg_cached = TRUE;
890 }
891 }
892 }
893
894 mail_cache_db_close_unlock(filename_env, cache_db_env);
895
896 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
897
898 if (r != MAIL_NO_ERROR) {
899 res = r;
900 goto free_mmapstr;
901 }
902
903 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
904 if (r < 0) {
905 res = MAIL_ERROR_MEMORY;
906 goto free_mmapstr;
907 }
908
909 /* add flags */
910
911 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
912 mailmessage * msg;
913
914 msg = carray_get(env_list->msg_tab, i);
915
916 if (msg->msg_flags == NULL) {
917 struct mail_flags * flags;
918
919 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
920 msg->msg_index, &flags);
921 if (r == MAIL_NO_ERROR) {
922 msg->msg_flags = flags;
923 }
924 else {
925 msg->msg_flags = mail_flags_new_empty();
926 if (msg->msg_fields == NULL) {
927 msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED;
928 mailmessage_check(msg);
929 }
930 }
931 }
932 }
933
934 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
935
936 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
937 if (r < 0) {
938 res = MAIL_ERROR_MEMORY;
939 goto free_mmapstr;
940 }
941
942 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
943 if (r < 0) {
944 res = MAIL_ERROR_MEMORY;
945 goto close_db_env;
946 }
947
948 /* must write cache */
949
950 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
951 mailmessage * msg;
952
953 msg = carray_get(env_list->msg_tab, i);
954
955 if (msg->msg_fields != NULL) {
956 if (!msg->msg_cached) {
957 r = write_cached_envelope(cache_db_env, mmapstr,
958 session, msg->msg_index, msg->msg_fields);
959 }
960 }
961
962 if (msg->msg_flags != NULL) {
963 r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr,
964 msg->msg_index, msg->msg_flags);
965 }
966 }
967
968 first = 0;
969 last = 0;
970 if (carray_count(env_list->msg_tab) > 0) {
971 mailmessage * msg;
972
973 msg = carray_get(env_list->msg_tab, 0);
974 first = msg->msg_index;
975
976 msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1);
977 last = msg->msg_index;
978 }
979
980 /* write articles sequence */
981
982 write_article_seq(session, first, last);
983
984 /* flush cache */
985
986 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
987
988 /* remove cache files */
989
990 snprintf(cache_dir, PATH_MAX, "%s/%s",
991 cached_data->nntp_cache_directory, ancestor_data->nntp_group_name);
992
993 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
994 mail_cache_db_close_unlock(filename_env, cache_db_env);
995 mmap_string_free(mmapstr);
996
997 maildriver_message_cache_clean_up(cache_dir, env_list,
998 get_uid_from_filename);
999
1000 return MAIL_NO_ERROR;
1001
1002 close_db_env:
1003 mail_cache_db_close_unlock(filename_env, cache_db_env);
1004 free_mmapstr:
1005 mmap_string_free(mmapstr);
1006 err:
1007 return res;
1008}
1009
1010static int
1011nntpdriver_cached_get_messages_list(mailsession * session,
1012 struct mailmessage_list ** result)
1013{
1014 return nntp_get_messages_list(get_ancestor(session), session,
1015 nntp_cached_message_driver, result);
1016}
1017
1018static int nntpdriver_cached_get_message(mailsession * session,
1019 uint32_t num, mailmessage ** result)
1020{
1021 mailmessage * msg_info;
1022 int r;
1023
1024 msg_info = mailmessage_new();
1025 if (msg_info == NULL)
1026 return MAIL_ERROR_MEMORY;
1027
1028 r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0);
1029 if (r != MAIL_NO_ERROR) {
1030 mailmessage_free(msg_info);
1031 return r;
1032 }
1033
1034 * result = msg_info;
1035
1036 return MAIL_NO_ERROR;
1037}
1038
1039static int nntpdriver_cached_noop(mailsession * session)
1040{
1041 return mailsession_noop(get_ancestor(session));
1042}
1043
1044static int nntpdriver_cached_get_message_by_uid(mailsession * session,
1045 const char * uid,
1046 mailmessage ** result)
1047{
1048 uint32_t num;
1049 char * p;
1050
1051 if (uid == NULL)
1052 return MAIL_ERROR_INVAL;
1053
1054 num = strtoul(uid, &p, 10);
1055 if ((p == uid) || (* p != '\0'))
1056 return MAIL_ERROR_INVAL;
1057
1058 return nntpdriver_cached_get_message(session, num, result);
1059}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
new file mode 100644
index 0000000..c0264de
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_CACHED_H
37
38#define NNTPDRIVER_CACHED_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * nntp_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
new file mode 100644
index 0000000..131b689
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c
@@ -0,0 +1,365 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_cached_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "nntpdriver.h"
46#include "nntpdriver_tools.h"
47#include "nntpdriver_cached.h"
48#include "nntpdriver_message.h"
49#include "generic_cache.h"
50
51static int nntp_prefetch(mailmessage * msg_info);
52
53static void nntp_prefetch_free(struct generic_message_t * msg);
54
55static int nntp_initialize(mailmessage * msg_info);
56
57static int nntp_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int nntp_fetch_size(mailmessage * msg_info,
62 size_t * result);
63
64static void nntp_uninitialize(mailmessage * msg_info);
65
66static void nntp_flush(mailmessage * msg_info);
67
68static void nntp_check(mailmessage * msg_info);
69
70static int nntp_get_flags(mailmessage * msg_info,
71 struct mail_flags ** result);
72
73static mailmessage_driver local_nntp_cached_message_driver = {
74 .msg_name = "nntp-cached",
75
76 .msg_initialize = nntp_initialize,
77 .msg_uninitialize = nntp_uninitialize,
78
79 .msg_flush = nntp_flush,
80 .msg_check = nntp_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = nntp_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = nntp_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = nntp_get_flags,
96};
97
98mailmessage_driver * nntp_cached_message_driver =
99&local_nntp_cached_message_driver;
100
101static inline struct nntp_cached_session_state_data *
102get_cached_session_data(mailmessage * msg)
103{
104 return msg->msg_session->sess_data;
105}
106
107static inline mailsession * get_ancestor_session(mailmessage * msg)
108{
109 return get_cached_session_data(msg)->nntp_ancestor;
110}
111
112static inline struct nntp_session_state_data *
113get_ancestor_session_data(mailmessage * msg)
114{
115 return get_ancestor_session(msg)->sess_data;
116}
117
118static inline newsnntp *
119get_nntp_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->nntp_session;
122}
123
124static int nntp_prefetch(mailmessage * msg_info)
125{
126 char * msg_content;
127 size_t msg_length;
128 struct generic_message_t * msg;
129 int r;
130 struct nntp_cached_session_state_data * cached_data;
131 struct nntp_session_state_data * ancestor_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 ancestor_data = get_ancestor_session_data(msg_info);
139
140 snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory,
141 ancestor_data->nntp_group_name, msg_info->msg_index);
142
143 r = generic_cache_read(filename, &msg_content, &msg_length);
144 if (r == MAIL_NO_ERROR) {
145 msg = msg_info->msg_data;
146
147 msg->msg_message = msg_content;
148 msg->msg_length = msg_length;
149
150 return MAIL_NO_ERROR;
151 }
152
153 /* we get the message through the network */
154
155 r = nntpdriver_article(get_ancestor_session(msg_info),
156 msg_info->msg_index, &msg_content,
157 &msg_length);
158
159 if (r != MAIL_NO_ERROR)
160 return r;
161
162 /* we write the message cache */
163
164 generic_cache_store(filename, msg_content, msg_length);
165
166 msg = msg_info->msg_data;
167
168 msg->msg_message = msg_content;
169 msg->msg_length = msg_length;
170
171 return MAIL_NO_ERROR;
172}
173
174static void nntp_prefetch_free(struct generic_message_t * msg)
175{
176 if (msg->msg_message != NULL) {
177 mmap_string_unref(msg->msg_message);
178 msg->msg_message = NULL;
179 }
180}
181
182static int nntp_initialize(mailmessage * msg_info)
183{
184 struct generic_message_t * msg;
185 int r;
186 char * uid;
187 char static_uid[20];
188
189 snprintf(static_uid, 20, "%u", msg_info->msg_index);
190 uid = strdup(static_uid);
191 if (uid == NULL)
192 return MAIL_ERROR_MEMORY;
193
194 r = mailmessage_generic_initialize(msg_info);
195 if (r != MAIL_NO_ERROR) {
196 free(uid);
197 return r;
198 }
199
200 msg = msg_info->msg_data;
201 msg->msg_prefetch = nntp_prefetch;
202 msg->msg_prefetch_free = nntp_prefetch_free;
203 msg_info->msg_uid = uid;
204
205 return MAIL_NO_ERROR;
206}
207
208
209static void nntp_uninitialize(mailmessage * msg_info)
210{
211 mailmessage_generic_uninitialize(msg_info);
212}
213
214#define FLAGS_NAME "flags.db"
215
216static void nntp_flush(mailmessage * msg_info)
217{
218 mailmessage_generic_flush(msg_info);
219}
220
221
222static void nntp_check(mailmessage * msg_info)
223{
224 int r;
225
226 if (msg_info->msg_flags != NULL) {
227 r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store,
228 msg_info);
229 /* ignore errors */
230 }
231}
232
233static int nntp_fetch_header(mailmessage * msg_info,
234 char ** result,
235 size_t * result_len)
236{
237 struct generic_message_t * msg;
238 char * headers;
239 size_t headers_length;
240 struct nntp_cached_session_state_data * cached_data;
241 struct nntp_session_state_data * ancestor_data;
242 int r;
243 char filename[PATH_MAX];
244
245 msg = msg_info->msg_data;
246
247 if (msg->msg_message != NULL)
248 return mailmessage_generic_fetch_header(msg_info,
249 result, result_len);
250
251 /* we try the cached message */
252
253 cached_data = get_cached_session_data(msg_info);
254
255 ancestor_data = get_ancestor_session_data(msg_info);
256
257 snprintf(filename, PATH_MAX, "%s/%s/%i-header",
258 cached_data->nntp_cache_directory,
259 ancestor_data->nntp_group_name, msg_info->msg_index);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message through the network */
270
271 r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 /* we write the message cache */
277
278 generic_cache_store(filename, headers, headers_length);
279
280 * result = headers;
281 * result_len = headers_length;
282
283 return MAIL_NO_ERROR;
284}
285
286static int nntp_fetch_size(mailmessage * msg_info,
287 size_t * result)
288{
289 return nntpdriver_size(get_ancestor_session(msg_info),
290 msg_info->msg_index, result);
291}
292
293static int nntp_get_flags(mailmessage * msg_info,
294 struct mail_flags ** result)
295{
296 int r;
297 struct mail_flags * flags;
298 struct mail_cache_db * cache_db_flags;
299 char filename_flags[PATH_MAX];
300 int res;
301 MMAPString * mmapstr;
302
303 if (msg_info->msg_flags != NULL) {
304 * result = msg_info->msg_flags;
305
306 return MAIL_NO_ERROR;
307 }
308
309 flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index);
310
311 if (flags == NULL) {
312 struct nntp_cached_session_state_data * cached_data;
313 struct nntp_session_state_data * ancestor_data;
314
315 cached_data = get_cached_session_data(msg_info);
316
317 ancestor_data = get_ancestor_session_data(msg_info);
318 if (ancestor_data->nntp_group_name == NULL) {
319 res = MAIL_ERROR_BAD_STATE;
320 goto err;
321 }
322
323 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
324 cached_data->nntp_flags_directory,
325 ancestor_data->nntp_group_name, FLAGS_NAME);
326
327 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
328 if (r < 0) {
329 res = MAIL_ERROR_MEMORY;
330 goto err;
331 }
332
333 mmapstr = mmap_string_new("");
334 if (mmapstr == NULL) {
335 res = MAIL_ERROR_MEMORY;
336 goto close_db_flags;
337 }
338
339 r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr,
340 msg_info->msg_index, &flags);
341 if (r != MAIL_NO_ERROR) {
342 flags = mail_flags_new_empty();
343 if (flags == NULL) {
344 res = MAIL_ERROR_MEMORY;
345 goto free_mmapstr;
346 }
347 }
348
349 mmap_string_free(mmapstr);
350 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
351 }
352
353 msg_info->msg_flags = flags;
354
355 * result = flags;
356
357 return MAIL_NO_ERROR;
358
359 free_mmapstr:
360 mmap_string_free(mmapstr);
361 close_db_flags:
362 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
363 err:
364 return res;
365}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
new file mode 100644
index 0000000..f515d48
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef NNTPDRIVER_CACHED_MESSAGE_H
39
40#define NNTPDRIVER_CACHED_MESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * nntp_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.c b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
new file mode 100644
index 0000000..117bc56
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.c
@@ -0,0 +1,169 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_message.h"
37
38#include "mailmessage_tools.h"
39#include "nntpdriver_tools.h"
40#include "nntpdriver.h"
41#include "newsnntp.h"
42#include <string.h>
43#include <stdlib.h>
44
45static int nntp_prefetch(mailmessage * msg_info);
46
47static void nntp_prefetch_free(struct generic_message_t * msg);
48
49static int nntp_initialize(mailmessage * msg_info);
50
51static int nntp_fetch_header(mailmessage * msg_info,
52 char ** result,
53 size_t * result_len);
54
55static int nntp_fetch_size(mailmessage * msg_info,
56 size_t * result);
57
58static mailmessage_driver local_nntp_message_driver = {
59 .msg_name = "nntp",
60
61 .msg_initialize = nntp_initialize,
62 .msg_uninitialize = mailmessage_generic_uninitialize,
63
64 .msg_flush = mailmessage_generic_flush,
65 .msg_check = NULL,
66
67 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
68
69 .msg_fetch = mailmessage_generic_fetch,
70 .msg_fetch_header = nntp_fetch_header,
71 .msg_fetch_body = mailmessage_generic_fetch_body,
72 .msg_fetch_size = nntp_fetch_size,
73 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
74 .msg_fetch_section = mailmessage_generic_fetch_section,
75 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
76 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
77 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
78 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
79
80 .msg_get_flags = NULL,
81};
82
83mailmessage_driver * nntp_message_driver = &local_nntp_message_driver;
84
85static int nntp_prefetch(mailmessage * msg_info)
86{
87 char * msg_content;
88 size_t msg_length;
89 struct generic_message_t * msg;
90 int r;
91
92 r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index,
93 &msg_content, &msg_length);
94 if (r != MAIL_NO_ERROR)
95 return r;
96
97 msg = msg_info->msg_data;
98
99 msg->msg_message = msg_content;
100 msg->msg_length = msg_length;
101
102 return MAIL_NO_ERROR;
103}
104
105static void nntp_prefetch_free(struct generic_message_t * msg)
106{
107 if (msg->msg_message != NULL) {
108 mmap_string_unref(msg->msg_message);
109 msg->msg_message = NULL;
110 }
111}
112
113static int nntp_initialize(mailmessage * msg_info)
114{
115 struct generic_message_t * msg;
116 int r;
117 char * uid;
118 char static_uid[20];
119
120 snprintf(static_uid, 20, "%u", msg_info->msg_index);
121 uid = strdup(static_uid);
122 if (uid == NULL)
123 return MAIL_ERROR_MEMORY;
124
125 r = mailmessage_generic_initialize(msg_info);
126 if (r != MAIL_NO_ERROR) {
127 free(uid);
128 return r;
129 }
130
131 msg = msg_info->msg_data;
132 msg->msg_prefetch = nntp_prefetch;
133 msg->msg_prefetch_free = nntp_prefetch_free;
134 msg_info->msg_uid = uid;
135
136 return MAIL_NO_ERROR;
137}
138
139static int nntp_fetch_header(mailmessage * msg_info,
140 char ** result,
141 size_t * result_len)
142{
143 struct generic_message_t * msg;
144 char * headers;
145 size_t headers_length;
146 int r;
147
148 msg = msg_info->msg_data;
149
150 if (msg->msg_message != NULL)
151 return mailmessage_generic_fetch_header(msg_info,
152 result, result_len);
153
154 r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index,
155 &headers, &headers_length);
156 if (r != MAIL_NO_ERROR)
157 return r;
158
159 * result = headers;
160 * result_len = headers_length;
161
162 return MAIL_NO_ERROR;
163}
164
165static int nntp_fetch_size(mailmessage * msg_info,
166 size_t * result)
167{
168 return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result);
169}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_message.h b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
new file mode 100644
index 0000000..15e80b7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_MESSAGE_H
37
38#define NNTPDRIVER_MESSAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/nntpdriver_types.h>
45
46extern mailmessage_driver * nntp_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
new file mode 100644
index 0000000..eef0953
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c
@@ -0,0 +1,563 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpdriver_tools.h"
37
38#include "mail.h"
39#include "nntpdriver.h"
40#include "nntpdriver_cached.h"
41#include "newsnntp.h"
42#include "maildriver_types.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mailmessage.h"
46#include "mail_cache_db.h"
47
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
52#include <string.h>
53#include <stdlib.h>
54
55int nntpdriver_nntp_error_to_mail_error(int error)
56{
57 switch (error) {
58 case NEWSNNTP_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case NEWSNNTP_ERROR_STREAM:
62 return MAIL_ERROR_STREAM;
63
64 case NEWSNNTP_ERROR_UNEXPECTED:
65 return MAIL_ERROR_PROGRAM_ERROR;
66
67 case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED:
68 return MAIL_ERROR_FOLDER_NOT_FOUND;
69
70 case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED:
71 case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER:
72 case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND:
73 return MAIL_ERROR_MSG_NOT_FOUND;
74
75 case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE:
76 case NEWSNNTP_ERROR_INVALID_RESPONSE:
77 return MAIL_ERROR_PARSE;
78
79 case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP:
80 return MAIL_ERROR_FOLDER_NOT_FOUND;
81
82 case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED:
83 return MAIL_ERROR_READONLY;
84
85 case NEWSNNTP_ERROR_POSTING_FAILED:
86 return MAIL_ERROR_APPEND;
87
88 case NEWSNNTP_ERROR_PROGRAM_ERROR:
89 return MAIL_ERROR_PROGRAM_ERROR;
90
91 case NEWSNNTP_ERROR_NO_PERMISSION:
92 return MAIL_ERROR_NO_PERMISSION;
93
94 case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD:
95 case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED:
96 return MAIL_ERROR_COMMAND_NOT_SUPPORTED;
97
98 case NEWSNNTP_ERROR_CONNECTION_REFUSED:
99 return MAIL_ERROR_CONNECT;
100
101 case NEWSNNTP_ERROR_MEMORY:
102 return MAIL_ERROR_MEMORY;
103
104 case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED:
105 return MAIL_ERROR_LOGIN;
106
107 case NEWSNNTP_ERROR_BAD_STATE:
108 return MAIL_ERROR_BAD_STATE;
109
110 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
111 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
112 default:
113 return MAIL_ERROR_INVAL;
114 }
115}
116
117static inline struct nntp_session_state_data *
118session_get_data(mailsession * session)
119{
120 return session->sess_data;
121}
122
123static inline newsnntp * session_get_nntp_session(mailsession * session)
124{
125 return session_get_data(session)->nntp_session;
126}
127
128static inline struct nntp_cached_session_state_data *
129cached_session_get_data(mailsession * session)
130{
131 return session->sess_data;
132}
133
134static inline mailsession * cached_session_get_ancestor(mailsession * session)
135{
136 return cached_session_get_data(session)->nntp_ancestor;
137}
138
139static inline struct nntp_session_state_data *
140cached_session_get_ancestor_data(mailsession * session)
141{
142 return session_get_data(cached_session_get_ancestor(session));
143}
144
145static inline newsnntp * cached_session_get_nntp_session(mailsession * session)
146{
147 return session_get_nntp_session(cached_session_get_ancestor(session));
148}
149
150
151int nntpdriver_authenticate_password(mailsession * session)
152{
153 struct nntp_session_state_data * data;
154 int r;
155
156 data = session_get_data(session);
157
158 if (data->nntp_password == NULL)
159 return MAIL_ERROR_LOGIN;
160
161 r = newsnntp_authinfo_password(session_get_nntp_session(session),
162 data->nntp_password);
163
164 return nntpdriver_nntp_error_to_mail_error(r);
165}
166
167int nntpdriver_mode_reader(mailsession * session)
168{
169 int done;
170 int r;
171
172 done = FALSE;
173
174 do {
175 r = newsnntp_mode_reader(session_get_nntp_session(session));
176
177 switch (r) {
178 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
179 r = nntpdriver_authenticate_user(session);
180 if (r != MAIL_NO_ERROR)
181 return r;
182 break;
183
184 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
185 r = nntpdriver_authenticate_password(session);
186 if (r != MAIL_NO_ERROR)
187 return r;
188 break;
189
190 case NEWSNNTP_NO_ERROR:
191 done = TRUE;
192 break;
193
194 default:
195 done = TRUE;
196 break;
197 }
198 }
199 while (!done);
200
201 return MAIL_NO_ERROR;
202}
203
204int nntpdriver_authenticate_user(mailsession * session)
205{
206 struct nntp_session_state_data * data;
207 int r;
208
209 data = session_get_data(session);
210
211 if (data->nntp_userid == NULL)
212 return MAIL_ERROR_LOGIN;
213
214 r = newsnntp_authinfo_username(session_get_nntp_session(session),
215 data->nntp_userid);
216
217 switch (r) {
218 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
219 return nntpdriver_authenticate_password(session);
220
221 default:
222 return nntpdriver_nntp_error_to_mail_error(r);
223 }
224}
225
226int nntpdriver_article(mailsession * session, uint32_t index,
227 char ** result,
228 size_t * result_len)
229{
230 char * msg_content;
231 size_t msg_length;
232 int r;
233 int done;
234
235 done = FALSE;
236 do {
237 r = newsnntp_article(session_get_nntp_session(session),
238 index, &msg_content, &msg_length);
239
240 switch (r) {
241 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
242 r = nntpdriver_authenticate_user(session);
243 if (r != MAIL_NO_ERROR)
244 return r;
245 break;
246
247 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
248 r = nntpdriver_authenticate_password(session);
249 if (r != MAIL_NO_ERROR)
250 return r;
251 break;
252
253 case NEWSNNTP_NO_ERROR:
254 done = TRUE;
255 break;
256
257 default:
258 return nntpdriver_nntp_error_to_mail_error(r);
259 }
260 }
261 while (!done);
262
263 * result = msg_content;
264 * result_len = msg_length;
265
266 return MAIL_NO_ERROR;
267}
268
269int nntpdriver_head(mailsession * session, uint32_t index,
270 char ** result,
271 size_t * result_len)
272{
273 char * headers;
274 size_t headers_length;
275 int r;
276 int done;
277
278 done = FALSE;
279 do {
280 r = newsnntp_head(session_get_nntp_session(session),
281 index, &headers, &headers_length);
282
283 switch (r) {
284 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
285 r = nntpdriver_authenticate_user(session);
286 if (r != MAIL_NO_ERROR)
287 return r;
288 break;
289
290 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
291 r = nntpdriver_authenticate_password(session);
292 if (r != MAIL_NO_ERROR)
293 return r;
294 break;
295
296 case NEWSNNTP_NO_ERROR:
297 done = TRUE;
298 break;
299
300 default:
301 return nntpdriver_nntp_error_to_mail_error(r);
302 }
303 }
304 while (!done);
305
306 * result = headers;
307 * result_len = headers_length;
308
309 return MAIL_NO_ERROR;
310}
311
312int nntpdriver_size(mailsession * session, uint32_t index,
313 size_t * result)
314{
315 newsnntp * nntp;
316 struct newsnntp_xover_resp_item * item;
317 int r;
318 int done;
319
320 nntp = session_get_nntp_session(session);
321
322 done = FALSE;
323 do {
324 r = newsnntp_xover_single(nntp, index, &item);
325 switch (r) {
326 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
327 r = nntpdriver_authenticate_user(session);
328 if (r != MAIL_NO_ERROR)
329 return r;
330 break;
331
332 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
333 r = nntpdriver_authenticate_password(session);
334 if (r != MAIL_NO_ERROR)
335 return r;
336 break;
337
338 case NEWSNNTP_NO_ERROR:
339 done = TRUE;
340 break;
341
342 default:
343 return nntpdriver_nntp_error_to_mail_error(r);
344 }
345 }
346 while (!done);
347
348 * result = item->ovr_size;
349
350 xover_resp_item_free(item);
351
352 return MAIL_NO_ERROR;
353}
354
355int
356nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
357 MMAPString * mmapstr,
358 uint32_t num,
359 struct mail_flags ** result)
360{
361 int r;
362 char keyname[PATH_MAX];
363 struct mail_flags * flags;
364 int res;
365
366 snprintf(keyname, PATH_MAX, "%u-flags", num);
367
368 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
369 if (r != MAIL_NO_ERROR) {
370 res = r;
371 goto err;
372 }
373
374 * result = flags;
375
376 return MAIL_NO_ERROR;
377
378 err:
379 return res;
380}
381
382int
383nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
384 MMAPString * mmapstr,
385 uint32_t num,
386 struct mail_flags * flags)
387{
388 int r;
389 char keyname[PATH_MAX];
390 int res;
391
392 snprintf(keyname, PATH_MAX, "%u-flags", num);
393
394 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
395 if (r != MAIL_NO_ERROR) {
396 res = r;
397 goto err;
398 }
399
400 return MAIL_NO_ERROR;
401
402 err:
403 return res;
404}
405
406
407
408int nntpdriver_select_folder(mailsession * session, char * mb)
409{
410 int r;
411 struct newsnntp_group_info * info;
412 newsnntp * nntp_session;
413 struct nntp_session_state_data * data;
414 char * new_name;
415 int done;
416
417 data = session_get_data(session);
418
419 if (!data->nntp_mode_reader) {
420 r = nntpdriver_mode_reader(session);
421 if (r != MAIL_NO_ERROR)
422 return r;
423
424 data->nntp_mode_reader = TRUE;
425 }
426
427 if (data->nntp_group_name != NULL)
428 if (strcmp(data->nntp_group_name, mb) == 0)
429 return MAIL_NO_ERROR;
430
431 nntp_session = session_get_nntp_session(session);
432
433 done = FALSE;
434 do {
435 r = newsnntp_group(nntp_session, mb, &info);
436
437 switch (r) {
438 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME:
439 r = nntpdriver_authenticate_user(session);
440 if (r != MAIL_NO_ERROR)
441 return r;
442 break;
443
444 case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD:
445 r = nntpdriver_authenticate_password(session);
446 if (r != MAIL_NO_ERROR)
447 return r;
448 break;
449
450 case NEWSNNTP_NO_ERROR:
451 done = TRUE;
452 break;
453
454 default:
455 return nntpdriver_nntp_error_to_mail_error(r);
456 }
457
458 }
459 while (!done);
460
461 new_name = strdup(mb);
462 if (new_name == NULL)
463 return MAIL_ERROR_MEMORY;
464
465 if (data->nntp_group_name != NULL)
466 free(data->nntp_group_name);
467 data->nntp_group_name = new_name;
468 if (data->nntp_group_info != NULL)
469 newsnntp_group_free(data->nntp_group_info);
470 data->nntp_group_info = info;
471
472 return MAIL_NO_ERROR;
473}
474
475
476int nntp_get_messages_list(mailsession * nntp_session,
477 mailsession * session,
478 mailmessage_driver * driver,
479 struct mailmessage_list ** result)
480{
481 carray * tab;
482 struct mailmessage_list * env_list;
483 uint32_t i;
484 int res;
485 int r;
486 struct nntp_session_state_data * data;
487 struct newsnntp_group_info * group_info;
488 uint32_t max;
489 unsigned int cur;
490
491 data = session_get_data(nntp_session);
492
493 if (data->nntp_group_name == NULL) {
494 res = MAIL_ERROR_BAD_STATE;
495 goto err;
496 }
497
498 r = nntpdriver_select_folder(nntp_session, data->nntp_group_name);
499 if (r != MAIL_NO_ERROR) {
500 res = r;
501 goto err;
502 }
503
504 group_info = data->nntp_group_info;
505
506 if (group_info == NULL) {
507 res = MAIL_ERROR_BAD_STATE;
508 goto err;
509 }
510
511 max = group_info->grp_first;
512 if (data->nntp_max_articles != 0) {
513 if (group_info->grp_last - data->nntp_max_articles + 1 > max)
514 max = group_info->grp_last - data->nntp_max_articles + 1;
515 }
516
517 tab = carray_new(128);
518 if (tab == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 for(i = max ; i <= group_info->grp_last ; i++) {
524 mailmessage * msg;
525
526 msg = mailmessage_new();
527 if (msg == NULL) {
528 res = MAIL_ERROR_MEMORY;
529 goto free_list;
530 }
531
532 r = mailmessage_init(msg, session, driver, i, 0);
533 if (r != MAIL_NO_ERROR) {
534 mailmessage_free(msg);
535 res = r;
536 goto free_list;
537 }
538
539 r = carray_add(tab, msg, NULL);
540 if (r < 0) {
541 mailmessage_free(msg);
542 res = MAIL_ERROR_MEMORY;
543 goto free_list;
544 }
545 }
546
547 env_list = mailmessage_list_new(tab);
548 if (env_list == NULL) {
549 res = MAIL_ERROR_MEMORY;
550 goto free_list;
551 }
552
553 * result = env_list;
554
555 return MAIL_NO_ERROR;
556
557 free_list:
558 for(cur = 0 ; cur < carray_count(tab) ; cur ++)
559 mailmessage_free(carray_get(tab, cur));
560 carray_free(tab);
561 err:
562 return res;
563}
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
new file mode 100644
index 0000000..8ca9d16
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h
@@ -0,0 +1,88 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_TOOLS_H
37
38#define NNTPDRIVER_TOOLS_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mail_cache_db_types.h"
45#include "nntpdriver_types.h"
46
47int nntpdriver_nntp_error_to_mail_error(int error);
48
49int nntpdriver_authenticate_password(mailsession * session);
50
51int nntpdriver_authenticate_user(mailsession * session);
52
53int nntpdriver_article(mailsession * session, uint32_t index,
54 char ** result, size_t * result_len);
55
56int nntpdriver_head(mailsession * session, uint32_t index,
57 char ** result,
58 size_t * result_len);
59
60int nntpdriver_size(mailsession * session, uint32_t index,
61 size_t * result);
62
63int
64nntpdriver_get_cached_flags(struct mail_cache_db * cache_db,
65 MMAPString * mmapstr,
66 uint32_t num,
67 struct mail_flags ** result);
68
69int
70nntpdriver_write_cached_flags(struct mail_cache_db * cache_db,
71 MMAPString * mmapstr,
72 uint32_t num,
73 struct mail_flags * flags);
74
75int nntpdriver_select_folder(mailsession * session, char * mb);
76
77int nntp_get_messages_list(mailsession * nntp_session,
78 mailsession * session,
79 mailmessage_driver * driver,
80 struct mailmessage_list ** result);
81
82int nntpdriver_mode_reader(mailsession * session);
83
84#ifdef __cplusplus
85}
86#endif
87
88#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpdriver_types.h b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
new file mode 100644
index 0000000..7d4b74d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpdriver_types.h
@@ -0,0 +1,146 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPDRIVER_TYPES_H
37
38#define NNTPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/newsnntp.h>
44#include <libetpan/clist.h>
45#include <libetpan/generic_cache_types.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* NNTP driver for session */
53
54enum {
55 NNTPDRIVER_SET_MAX_ARTICLES = 1,
56};
57
58struct nntp_session_state_data {
59 newsnntp * nntp_session;
60 char * nntp_userid;
61 char * nntp_password;
62
63 struct newsnntp_group_info * nntp_group_info;
64 char * nntp_group_name;
65
66 clist * nntp_subscribed_list;
67
68 uint32_t nntp_max_articles;
69
70 int nntp_mode_reader;
71};
72
73/* cached NNTP driver for session */
74
75enum {
76 /* the mapping of the parameters should be the same as for nntp */
77 NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1,
78 /* cache specific */
79 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
80 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
81};
82
83struct nntp_cached_session_state_data {
84 mailsession * nntp_ancestor;
85 char nntp_cache_directory[PATH_MAX];
86 char nntp_flags_directory[PATH_MAX];
87 struct mail_flags_store * nntp_flags_store;
88};
89
90
91/* nntp storage */
92
93/*
94 nntp_mailstorage is the state data specific to the IMAP4rev1 storage.
95
96 - storage this is the storage to initialize.
97
98 - servername this is the name of the NNTP server
99
100 - port is the port to connect to, on the server.
101 you give 0 to use the default port.
102
103 - connection_type is the type of socket layer to use.
104 The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS.
105
106 - auth_type is the authenticate mechanism to use.
107 The value can be NNTP_AUTH_TYPE_PLAIN.
108
109 - login is the login of the POP3 account.
110
111 - password is the password of the POP3 account.
112
113 - cached if this value is != 0, a persistant cache will be
114 stored on local system.
115
116 - cache_directory is the location of the cache
117
118 - flags_directory is the location of the flags
119*/
120
121struct nntp_mailstorage {
122 char * nntp_servername;
123 uint16_t nntp_port;
124 char * nntp_command;
125 int nntp_connection_type;
126
127 int nntp_auth_type;
128 char * nntp_login;
129 char * nntp_password;
130
131 int nntp_cached;
132 char * nntp_cache_directory;
133 char * nntp_flags_directory;
134};
135
136/* this is the type of NNTP authentication */
137
138enum {
139 NNTP_AUTH_TYPE_PLAIN, /* plain text authentication */
140};
141
142#ifdef __cplusplus
143}
144#endif
145
146#endif
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.c b/libetpan/src/driver/implementation/nntp/nntpstorage.c
new file mode 100644
index 0000000..8d0e4ff
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.c
@@ -0,0 +1,267 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "nntpstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "maildriver.h"
42#include "nntpdriver.h"
43#include "nntpdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "mail.h"
46
47/* nntp storage */
48
49#define NNTP_DEFAULT_PORT 119
50#define NNTPS_DEFAULT_PORT 563
51
52static int nntp_mailstorage_connect(struct mailstorage * storage);
53static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
54 char * pathname, mailsession ** result);
55static void nntp_mailstorage_uninitialize(struct mailstorage * storage);
56
57static mailstorage_driver nntp_mailstorage_driver = {
58 .sto_name = "nntp",
59 .sto_connect = nntp_mailstorage_connect,
60 .sto_get_folder_session = nntp_mailstorage_get_folder_session,
61 .sto_uninitialize = nntp_mailstorage_uninitialize,
62};
63
64int nntp_mailstorage_init(struct mailstorage * storage,
65 char * nn_servername, uint16_t nn_port,
66 char * nn_command,
67 int nn_connection_type, int nn_auth_type,
68 char * nn_login, char * nn_password,
69 int nn_cached, char * nn_cache_directory, char * nn_flags_directory)
70{
71 struct nntp_mailstorage * nntp_storage;
72 int res;
73
74 nntp_storage = malloc(sizeof(* nntp_storage));
75 if (nntp_storage == NULL) {
76 res = MAIL_ERROR_MEMORY;
77 goto err;
78 }
79
80 nntp_storage->nntp_servername = strdup(nn_servername);
81 if (nntp_storage->nntp_servername == NULL) {
82 res = MAIL_ERROR_MEMORY;
83 goto free;
84 }
85
86 nntp_storage->nntp_connection_type = nn_connection_type;
87
88 if (nn_port == 0) {
89 switch (nn_connection_type) {
90 case CONNECTION_TYPE_PLAIN:
91 case CONNECTION_TYPE_COMMAND:
92 nn_port = NNTP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 nn_port = NNTPS_DEFAULT_PORT;
98 break;
99
100 default:
101 res = MAIL_ERROR_INVAL;
102 goto free_servername;
103 }
104 }
105
106 nntp_storage->nntp_port = nn_port;
107
108 if (nn_command != NULL) {
109 nntp_storage->nntp_command = strdup(nn_command);
110 if (nntp_storage->nntp_command == NULL) {
111 res = MAIL_ERROR_MEMORY;
112 goto free_servername;
113 }
114 }
115 else
116 nntp_storage->nntp_command = NULL;
117
118 nntp_storage->nntp_auth_type = nn_auth_type;
119
120 if (nn_login != NULL) {
121 nntp_storage->nntp_login = strdup(nn_login);
122 if (nntp_storage->nntp_login == NULL) {
123 res = MAIL_ERROR_MEMORY;
124 goto free_command;
125 }
126 }
127 else
128 nntp_storage->nntp_login = NULL;
129
130 if (nn_password != NULL) {
131 nntp_storage->nntp_password = strdup(nn_password);
132 if (nntp_storage->nntp_password == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto free_login;
135 }
136 }
137 else
138 nntp_storage->nntp_password = NULL;
139
140 nntp_storage->nntp_cached = nn_cached;
141
142 if (nn_cached && (nn_cache_directory != NULL) &&
143 (nn_flags_directory != NULL)) {
144 nntp_storage->nntp_cache_directory = strdup(nn_cache_directory);
145 if (nntp_storage->nntp_cache_directory == NULL) {
146 res = MAIL_ERROR_MEMORY;
147 goto free_password;
148 }
149 nntp_storage->nntp_flags_directory = strdup(nn_flags_directory);
150 if (nntp_storage->nntp_flags_directory == NULL) {
151 res = MAIL_ERROR_MEMORY;
152 goto free_cache_directory;
153 }
154 }
155 else {
156 nntp_storage->nntp_cached = FALSE;
157 nntp_storage->nntp_cache_directory = NULL;
158 nntp_storage->nntp_flags_directory = NULL;
159 }
160
161 storage->sto_data = nntp_storage;
162 storage->sto_driver = &nntp_mailstorage_driver;
163
164 return MAIL_NO_ERROR;
165
166 free_cache_directory:
167 free(nntp_storage->nntp_cache_directory);
168 free_password:
169 free(nntp_storage->nntp_password);
170 free_login:
171 free(nntp_storage->nntp_login);
172 free_command:
173 free(nn_command);
174 free_servername:
175 free(nntp_storage->nntp_servername);
176 free:
177 free(nntp_storage);
178 err:
179 return res;
180}
181
182static void nntp_mailstorage_uninitialize(struct mailstorage * storage)
183{
184 struct nntp_mailstorage * nntp_storage;
185
186 nntp_storage = storage->sto_data;
187
188 if (nntp_storage->nntp_flags_directory != NULL)
189 free(nntp_storage->nntp_flags_directory);
190 if (nntp_storage->nntp_cache_directory != NULL)
191 free(nntp_storage->nntp_cache_directory);
192 if (nntp_storage->nntp_password != NULL)
193 free(nntp_storage->nntp_password);
194 if (nntp_storage->nntp_login != NULL)
195 free(nntp_storage->nntp_login);
196 if (nntp_storage->nntp_command != NULL)
197 free(nntp_storage->nntp_command);
198 free(nntp_storage->nntp_servername);
199 free(nntp_storage);
200
201 storage->sto_data = NULL;
202}
203
204static int nntp_mailstorage_connect(struct mailstorage * storage)
205{
206 struct nntp_mailstorage * nntp_storage;
207 mailsession_driver * driver;
208 int r;
209 int res;
210 mailsession * session;
211
212 nntp_storage = storage->sto_data;
213
214 if (nntp_storage->nntp_cached)
215 driver = nntp_cached_session_driver;
216 else
217 driver = nntp_session_driver;
218
219 r = mailstorage_generic_connect(driver,
220 nntp_storage->nntp_servername,
221 nntp_storage->nntp_port, nntp_storage->nntp_command,
222 nntp_storage->nntp_connection_type,
223 NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY,
224 nntp_storage->nntp_cache_directory,
225 NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY,
226 nntp_storage->nntp_flags_directory,
227 &session);
228 switch (r) {
229 case MAIL_NO_ERROR_NON_AUTHENTICATED:
230 case MAIL_NO_ERROR_AUTHENTICATED:
231 case MAIL_NO_ERROR:
232 break;
233 default:
234 res = r;
235 goto err;
236 }
237
238 r = mailstorage_generic_auth(session, r,
239 nntp_storage->nntp_connection_type,
240 nntp_storage->nntp_login,
241 nntp_storage->nntp_password);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto free;
245 }
246
247 storage->sto_session = session;
248
249 return MAIL_NO_ERROR;
250
251 free:
252 mailsession_free(session);
253 err:
254 return res;
255}
256
257static int nntp_mailstorage_get_folder_session(struct mailstorage * storage,
258 char * pathname, mailsession ** result)
259{
260 int r;
261
262 r = mailsession_select_folder(storage->sto_session, pathname);
263
264 * result = storage->sto_session;
265
266 return MAIL_NO_ERROR;
267}
diff --git a/libetpan/src/driver/implementation/nntp/nntpstorage.h b/libetpan/src/driver/implementation/nntp/nntpstorage.h
new file mode 100644
index 0000000..7b046f4
--- a/dev/null
+++ b/libetpan/src/driver/implementation/nntp/nntpstorage.h
@@ -0,0 +1,93 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NNTPSTORAGE_H
37
38#define NNTPSTORAGE_H
39
40#include <libetpan/nntpdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46
47/*
48 nntp_mailstorage_init is the constructor for a NNTP storage
49
50 @param storage this is the storage to initialize.
51
52 @param servername this is the name of the NNTP server
53
54 @param port is the port to connect to, on the server.
55 you give 0 to use the default port.
56
57 @param command the command used to connect to the server instead of
58 allowing normal TCP connections to be used.
59
60 @param connection_type is the type of socket layer to use.
61 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
62 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
63 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
64 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
65
66 @param auth_type is the authenticate mechanism to use.
67 The value can be NNTP_AUTH_TYPE_PLAIN.
68
69 @param login is the login of the POP3 account.
70
71 @param password is the password of the POP3 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77
78 @param flags_directory is the location of the flags
79*/
80
81int nntp_mailstorage_init(struct mailstorage * storage,
82 char * nntp_servername, uint16_t nntp_port,
83 char * nntp_command,
84 int nntp_connection_type, int nntp_auth_type,
85 char * nntp_login, char * nntp_password,
86 int nntp_cached, char * nntp_cache_directory,
87 char * nntp_flags_directory);
88
89#ifdef __cplusplus
90}
91#endif
92
93#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.c b/libetpan/src/driver/implementation/pop3/pop3driver.c
new file mode 100644
index 0000000..ea69923
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver.c
@@ -0,0 +1,388 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "pop3driver_message.h"
42#include "maildriver_tools.h"
43#include "pop3driver_tools.h"
44#include "mailmessage.h"
45
46static int pop3driver_initialize(mailsession * session);
47
48static void pop3driver_uninitialize(mailsession * session);
49
50static int pop3driver_parameters(mailsession * session,
51 int id, void * value);
52
53static int pop3driver_connect_stream(mailsession * session, mailstream * s);
54
55static int pop3driver_starttls(mailsession * session);
56
57static int pop3driver_login(mailsession * session,
58 char * userid, char * password);
59
60static int pop3driver_logout(mailsession * session);
61
62static int pop3driver_noop(mailsession * session);
63
64static int pop3driver_status_folder(mailsession * session, char * mb,
65 uint32_t * result_messages, uint32_t * result_recent,
66 uint32_t * result_unseen);
67
68static int pop3driver_messages_number(mailsession * session, char * mb,
69 uint32_t * result);
70
71static int pop3driver_remove_message(mailsession * session, uint32_t num);
72
73static int pop3driver_get_messages_list(mailsession * session,
74 struct mailmessage_list ** result);
75
76static int pop3driver_get_message(mailsession * session,
77 uint32_t num, mailmessage ** result);
78
79static mailsession_driver local_pop3_session_driver = {
80 .sess_name = "pop3",
81
82 .sess_initialize = pop3driver_initialize,
83 .sess_uninitialize = pop3driver_uninitialize,
84
85 .sess_parameters = pop3driver_parameters,
86
87 .sess_connect_stream = pop3driver_connect_stream,
88 .sess_connect_path = NULL,
89 .sess_starttls = pop3driver_starttls,
90 .sess_login = pop3driver_login,
91 .sess_logout = pop3driver_logout,
92 .sess_noop = pop3driver_noop,
93
94 .sess_build_folder_name = NULL,
95 .sess_create_folder = NULL,
96 .sess_delete_folder = NULL,
97 .sess_rename_folder = NULL,
98 .sess_check_folder = NULL,
99 .sess_examine_folder = NULL,
100 .sess_select_folder = NULL,
101 .sess_expunge_folder = NULL,
102 .sess_status_folder = pop3driver_status_folder,
103 .sess_messages_number = pop3driver_messages_number,
104 .sess_recent_number = pop3driver_messages_number,
105 .sess_unseen_number = pop3driver_messages_number,
106 .sess_list_folders = NULL,
107 .sess_lsub_folders = NULL,
108 .sess_subscribe_folder = NULL,
109 .sess_unsubscribe_folder = NULL,
110
111 .sess_append_message = NULL,
112 .sess_append_message_flags = NULL,
113 .sess_copy_message = NULL,
114 .sess_move_message = NULL,
115
116 .sess_get_messages_list = pop3driver_get_messages_list,
117 .sess_get_envelopes_list = maildriver_generic_get_envelopes_list,
118 .sess_remove_message = pop3driver_remove_message,
119#if 0
120 .sess_search_messages = maildriver_generic_search_messages,
121#endif
122
123 .sess_get_message = pop3driver_get_message,
124 .sess_get_message_by_uid = NULL,
125};
126
127mailsession_driver * pop3_session_driver = &local_pop3_session_driver;
128
129static inline struct pop3_session_state_data *
130get_data(mailsession * session)
131{
132 return session->sess_data;
133}
134
135static mailpop3 * get_pop3_session(mailsession * session)
136{
137 return get_data(session)->pop3_session;
138}
139
140static int pop3driver_initialize(mailsession * session)
141{
142 struct pop3_session_state_data * data;
143 mailpop3 * pop3;
144
145 pop3 = mailpop3_new(0, NULL);
146 if (session == NULL)
147 goto err;
148
149 data = malloc(sizeof(* data));
150 if (data == NULL)
151 goto free;
152
153 data->pop3_session = pop3;
154 data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
155
156 session->sess_data = data;
157
158 return MAIL_NO_ERROR;
159
160 free:
161 mailpop3_free(pop3);
162 err:
163 return MAIL_ERROR_MEMORY;
164}
165
166static void pop3driver_uninitialize(mailsession * session)
167{
168 struct pop3_session_state_data * data;
169
170 data = get_data(session);
171
172 mailpop3_free(data->pop3_session);
173 free(data);
174
175 session->sess_data = data;
176}
177
178static int pop3driver_connect_stream(mailsession * session, mailstream * s)
179{
180 int r;
181
182 r = mailpop3_connect(get_pop3_session(session), s);
183
184 switch (r) {
185 case MAILPOP3_NO_ERROR:
186 return MAIL_NO_ERROR_NON_AUTHENTICATED;
187
188 default:
189 return pop3driver_pop3_error_to_mail_error(r);
190 }
191}
192
193static int pop3driver_starttls(mailsession * session)
194{
195 int r;
196 int fd;
197 mailstream_low * low;
198 mailstream_low * new_low;
199 mailpop3 * pop3;
200
201 pop3 = get_pop3_session(session);
202
203 r = mailpop3_stls(pop3);
204
205 switch (r) {
206 case MAILPOP3_NO_ERROR:
207 break;
208 default:
209 return pop3driver_pop3_error_to_mail_error(r);
210 }
211
212 low = mailstream_get_low(pop3->pop3_stream);
213 fd = mailstream_low_get_fd(low);
214 if (fd == -1)
215 return MAIL_ERROR_STREAM;
216
217 new_low = mailstream_low_ssl_open(fd);
218 if (new_low == NULL)
219 return MAIL_ERROR_STREAM;
220 mailstream_low_free(low);
221 mailstream_set_low(pop3->pop3_stream, new_low);
222
223 return MAIL_NO_ERROR;
224}
225
226static int pop3driver_parameters(mailsession * session,
227 int id, void * value)
228{
229 struct pop3_session_state_data * data;
230
231 data = get_data(session);
232
233 switch (id) {
234 case POP3DRIVER_SET_AUTH_TYPE:
235 {
236 int * param;
237
238 param = value;
239
240 data->pop3_auth_type = * param;
241 return MAIL_NO_ERROR;
242 }
243 }
244
245 return MAIL_ERROR_INVAL;
246}
247
248static int pop3driver_login(mailsession * session,
249 char * userid, char * password)
250{
251 int r;
252 carray * msg_tab;
253 struct pop3_session_state_data * data;
254
255 data = get_data(session);
256
257 switch (data->pop3_auth_type) {
258 case POP3DRIVER_AUTH_TYPE_TRY_APOP:
259 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
260 if (r != MAILPOP3_NO_ERROR)
261 r = mailpop3_login(get_pop3_session(session), userid, password);
262 break;
263
264 case POP3DRIVER_AUTH_TYPE_APOP:
265 r = mailpop3_login_apop(get_pop3_session(session), userid, password);
266 break;
267
268 default:
269 case POP3DRIVER_AUTH_TYPE_PLAIN:
270 r = mailpop3_login(get_pop3_session(session), userid, password);
271 break;
272 }
273
274 mailpop3_list(get_pop3_session(session), &msg_tab);
275
276 return pop3driver_pop3_error_to_mail_error(r);
277}
278
279static int pop3driver_logout(mailsession * session)
280{
281 int r;
282
283 r = mailpop3_quit(get_pop3_session(session));
284
285 return pop3driver_pop3_error_to_mail_error(r);
286}
287
288static int pop3driver_noop(mailsession * session)
289{
290 int r;
291
292 r = mailpop3_noop(get_pop3_session(session));
293
294 return pop3driver_pop3_error_to_mail_error(r);
295}
296
297static int pop3driver_status_folder(mailsession * session, char * mb,
298 uint32_t * result_messages,
299 uint32_t * result_recent,
300 uint32_t * result_unseen)
301{
302 uint32_t count;
303 int r;
304
305 r = pop3driver_messages_number(session, mb, &count);
306 if (r != MAIL_NO_ERROR)
307 return r;
308
309 * result_messages = count;
310 * result_recent = count;
311 * result_unseen = count;
312
313 return MAIL_NO_ERROR;
314}
315
316static int pop3driver_messages_number(mailsession * session, char * mb,
317 uint32_t * result)
318{
319 carray * msg_tab;
320
321 mailpop3_list(get_pop3_session(session), &msg_tab);
322
323 * result = carray_count(msg_tab) -
324 get_pop3_session(session)->pop3_deleted_count;
325
326 return MAIL_NO_ERROR;
327}
328
329
330/* messages operations */
331
332static int pop3driver_remove_message(mailsession * session, uint32_t num)
333{
334 mailpop3 * pop3;
335 int r;
336
337 pop3 = get_pop3_session(session);
338
339 r = mailpop3_dele(pop3, num);
340 switch (r) {
341 case MAILPOP3_ERROR_BAD_STATE:
342 return MAIL_ERROR_BAD_STATE;
343
344 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
345 return MAIL_ERROR_MSG_NOT_FOUND;
346
347 case MAILPOP3_ERROR_STREAM:
348 return MAIL_ERROR_STREAM;
349
350 case MAILPOP3_NO_ERROR:
351 return MAIL_NO_ERROR;
352
353 default:
354 return MAIL_ERROR_REMOVE;
355 }
356}
357
358static int pop3driver_get_messages_list(mailsession * session,
359 struct mailmessage_list ** result)
360{
361 mailpop3 * pop3;
362
363 pop3 = get_pop3_session(session);
364
365 return pop3_get_messages_list(pop3, session,
366 pop3_message_driver, result);
367}
368
369static int pop3driver_get_message(mailsession * session,
370 uint32_t num, mailmessage ** result)
371{
372 mailmessage * msg_info;
373 int r;
374
375 msg_info = mailmessage_new();
376 if (msg_info == NULL)
377 return MAIL_ERROR_MEMORY;
378
379 r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0);
380 if (r != MAIL_NO_ERROR) {
381 mailmessage_free(msg_info);
382 return r;
383 }
384
385 * result = msg_info;
386
387 return MAIL_NO_ERROR;
388}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.h b/libetpan/src/driver/implementation/pop3/pop3driver.h
new file mode 100644
index 0000000..b70f69e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_H
37
38#define POP3DRIVER_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * pop3_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
new file mode 100644
index 0000000..d3cc98e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
@@ -0,0 +1,899 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <fcntl.h>
43#include <string.h>
44#include <unistd.h>
45#include <stdlib.h>
46
47#include "mail.h"
48#include "mail_cache_db.h"
49
50#include "maildriver.h"
51#include "mailmessage.h"
52#include "pop3driver.h"
53#include "mailpop3.h"
54#include "generic_cache.h"
55#include "imfcache.h"
56#include "pop3driver_cached_message.h"
57#include "pop3driver_tools.h"
58#include "maildriver_tools.h"
59
60static int pop3driver_cached_initialize(mailsession * session);
61
62static void pop3driver_cached_uninitialize(mailsession * session);
63
64static int pop3driver_cached_parameters(mailsession * session,
65 int id, void * value);
66
67static int pop3driver_cached_connect_stream(mailsession * session,
68 mailstream * s);
69
70static int pop3driver_cached_starttls(mailsession * session);
71
72static int pop3driver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int pop3driver_cached_logout(mailsession * session);
76
77static int pop3driver_cached_check_folder(mailsession * session);
78
79static int pop3driver_cached_noop(mailsession * session);
80
81static int pop3driver_cached_expunge_folder(mailsession * session);
82
83static int pop3driver_cached_status_folder(mailsession * session,
84 char * mb, uint32_t * result_messages, uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int pop3driver_cached_messages_number(mailsession * session,
88 char * mb,
89 uint32_t * result);
90
91static int pop3driver_cached_recent_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94
95static int pop3driver_cached_unseen_number(mailsession * session,
96 char * mb,
97 uint32_t * result);
98
99static int pop3driver_cached_remove_message(mailsession * session,
100 uint32_t num);
101
102static int
103pop3driver_cached_get_messages_list(mailsession * session,
104 struct mailmessage_list ** result);
105
106static int
107pop3driver_cached_get_envelopes_list(mailsession * session,
108 struct mailmessage_list * env_list);
109
110static int pop3driver_cached_get_message(mailsession * session,
111 uint32_t num, mailmessage ** result);
112
113static int pop3driver_cached_get_message_by_uid(mailsession * session,
114 const char * uid, mailmessage ** result);
115
116static mailsession_driver local_pop3_cached_session_driver = {
117 .sess_name = "pop3-cached",
118
119 .sess_initialize = pop3driver_cached_initialize,
120 .sess_uninitialize = pop3driver_cached_uninitialize,
121
122 .sess_parameters = pop3driver_cached_parameters,
123
124 .sess_connect_stream = pop3driver_cached_connect_stream,
125 .sess_connect_path = NULL,
126 .sess_starttls = pop3driver_cached_starttls,
127 .sess_login = pop3driver_cached_login,
128 .sess_logout = pop3driver_cached_logout,
129 .sess_noop = pop3driver_cached_noop,
130
131 .sess_build_folder_name = NULL,
132 .sess_create_folder = NULL,
133 .sess_delete_folder = NULL,
134 .sess_rename_folder = NULL,
135 .sess_check_folder = pop3driver_cached_check_folder,
136 .sess_examine_folder = NULL,
137 .sess_select_folder = NULL,
138 .sess_expunge_folder = pop3driver_cached_expunge_folder,
139 .sess_status_folder = pop3driver_cached_status_folder,
140 .sess_messages_number = pop3driver_cached_messages_number,
141 .sess_recent_number = pop3driver_cached_recent_number,
142 .sess_unseen_number = pop3driver_cached_unseen_number,
143 .sess_list_folders = NULL,
144 .sess_lsub_folders = NULL,
145 .sess_subscribe_folder = NULL,
146 .sess_unsubscribe_folder = NULL,
147
148 .sess_append_message = NULL,
149 .sess_append_message_flags = NULL,
150 .sess_copy_message = NULL,
151 .sess_move_message = NULL,
152
153 .sess_get_messages_list = pop3driver_cached_get_messages_list,
154 .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list,
155 .sess_remove_message = pop3driver_cached_remove_message,
156#if 0
157 .sess_search_messages = maildriver_generic_search_messages,
158#endif
159
160 .sess_get_message = pop3driver_cached_get_message,
161 .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid,
162};
163
164mailsession_driver * pop3_cached_session_driver =
165&local_pop3_cached_session_driver;
166
167#define ENV_NAME "env.db"
168#define FLAGS_NAME "flags.db"
169
170
171static inline struct pop3_cached_session_state_data *
172get_cached_data(mailsession * session)
173{
174 return session->sess_data;
175}
176
177static inline mailsession * get_ancestor(mailsession * session)
178{
179 return get_cached_data(session)->pop3_ancestor;
180}
181
182static inline struct pop3_session_state_data *
183get_ancestor_data(mailsession * session)
184{
185 return get_ancestor(session)->sess_data;
186}
187
188static inline mailpop3 * get_pop3_session(mailsession * session)
189{
190 return get_ancestor_data(session)->pop3_session;
191}
192
193static int pop3driver_cached_initialize(mailsession * session)
194{
195 struct pop3_cached_session_state_data * data;
196
197 data = malloc(sizeof(* data));
198 if (data == NULL)
199 goto err;
200
201 data->pop3_flags_store = mail_flags_store_new();
202 if (data->pop3_flags_store == NULL)
203 goto free_data;
204
205 data->pop3_ancestor = mailsession_new(pop3_session_driver);
206 if (data->pop3_ancestor == NULL)
207 goto free_store;
208
209 data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE);
210 if (data->pop3_flags_hash == NULL)
211 goto free_session;
212
213 session->sess_data = data;
214
215 return MAIL_NO_ERROR;
216
217 free_session:
218 mailsession_free(data->pop3_ancestor);
219 free_store:
220 mail_flags_store_free(data->pop3_flags_store);
221 free_data:
222 free(data);
223 err:
224 return MAIL_ERROR_MEMORY;
225}
226
227static int pop3_flags_store_process(char * flags_directory,
228 struct mail_flags_store * flags_store)
229{
230 char filename_flags[PATH_MAX];
231 struct mail_cache_db * cache_db_flags;
232 MMAPString * mmapstr;
233 unsigned int i;
234 int r;
235 int res;
236
237 if (carray_count(flags_store->fls_tab) == 0)
238 return MAIL_NO_ERROR;
239
240 snprintf(filename_flags, PATH_MAX, "%s/%s",
241 flags_directory, FLAGS_NAME);
242
243 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
244 if (r < 0) {
245 res = MAIL_ERROR_FILE;
246 goto err;
247 }
248
249 mmapstr = mmap_string_new("");
250 if (mmapstr == NULL) {
251 res = MAIL_ERROR_MEMORY;
252 goto close_db_flags;
253 }
254
255 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
256 mailmessage * msg;
257
258 msg = carray_get(flags_store->fls_tab, i);
259
260 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
261 msg->msg_uid, msg->msg_flags);
262 }
263
264 mmap_string_free(mmapstr);
265 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
266
267 mail_flags_store_clear(flags_store);
268
269 return MAIL_NO_ERROR;
270
271 close_db_flags:
272 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
273 err:
274 return res;
275}
276
277static void pop3driver_cached_uninitialize(mailsession * session)
278{
279 struct pop3_cached_session_state_data * data;
280
281 data = get_cached_data(session);
282
283 pop3_flags_store_process(data->pop3_flags_directory,
284 data->pop3_flags_store);
285
286 mail_flags_store_free(data->pop3_flags_store);
287
288 chash_free(data->pop3_flags_hash);
289 mailsession_free(data->pop3_ancestor);
290 free(data);
291
292 session->sess_data = data;
293}
294
295static int pop3driver_cached_check_folder(mailsession * session)
296{
297 struct pop3_cached_session_state_data * pop3_data;
298
299 pop3_data = get_cached_data(session);
300
301 pop3_flags_store_process(pop3_data->pop3_flags_directory,
302 pop3_data->pop3_flags_store);
303
304 return MAIL_NO_ERROR;
305}
306
307static int pop3driver_cached_parameters(mailsession * session,
308 int id, void * value)
309{
310 struct pop3_cached_session_state_data * data;
311 int r;
312
313 data = get_cached_data(session);
314
315 switch (id) {
316 case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY:
317 strncpy(data->pop3_cache_directory, value, PATH_MAX);
318 data->pop3_cache_directory[PATH_MAX - 1] = '\0';
319
320 r = generic_cache_create_dir(data->pop3_cache_directory);
321 if (r != MAIL_NO_ERROR)
322 return r;
323
324 return MAIL_NO_ERROR;
325
326 case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY:
327 strncpy(data->pop3_flags_directory, value, PATH_MAX);
328 data->pop3_flags_directory[PATH_MAX - 1] = '\0';
329
330 r = generic_cache_create_dir(data->pop3_flags_directory);
331 if (r != MAIL_NO_ERROR)
332 return r;
333
334 return MAIL_NO_ERROR;
335
336 default:
337 return mailsession_parameters(data->pop3_ancestor, id, value);
338 }
339}
340
341static int pop3driver_cached_connect_stream(mailsession * session,
342 mailstream * s)
343{
344 int r;
345
346 r = mailsession_connect_stream(get_ancestor(session), s);
347 if (r != MAIL_NO_ERROR)
348 return r;
349
350 return MAIL_NO_ERROR;
351}
352
353static int pop3driver_cached_starttls(mailsession * session)
354{
355 return mailsession_starttls(get_ancestor(session));
356}
357
358
359static int pop3driver_cached_login(mailsession * session,
360 char * userid, char * password)
361{
362 return mailsession_login(get_ancestor(session), userid, password);
363}
364
365static int pop3driver_cached_logout(mailsession * session)
366{
367 struct pop3_cached_session_state_data * cached_data;
368
369 cached_data = get_cached_data(session);
370
371 pop3_flags_store_process(cached_data->pop3_flags_directory,
372 cached_data->pop3_flags_store);
373
374 return mailsession_logout(get_ancestor(session));
375}
376
377static int pop3driver_cached_noop(mailsession * session)
378{
379 return mailsession_noop(get_ancestor(session));
380}
381
382static int pop3driver_cached_expunge_folder(mailsession * session)
383{
384 int res;
385 struct pop3_cached_session_state_data * cached_data;
386 char filename_flags[PATH_MAX];
387 struct mail_cache_db * cache_db_flags;
388 MMAPString * mmapstr;
389 unsigned int i;
390 int r;
391 carray * msg_tab;
392 mailpop3 * pop3;
393
394 pop3 = get_pop3_session(session);
395
396 cached_data = get_cached_data(session);
397
398 pop3_flags_store_process(cached_data->pop3_flags_directory,
399 cached_data->pop3_flags_store);
400
401 snprintf(filename_flags, PATH_MAX, "%s/%s",
402 cached_data->pop3_flags_directory, FLAGS_NAME);
403
404 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
405 if (r < 0) {
406 res = MAIL_ERROR_MEMORY;
407 goto err;
408 }
409
410 mmapstr = mmap_string_new("");
411 if (mmapstr == NULL) {
412 res = MAIL_ERROR_MEMORY;
413 goto close_db_flags;
414 }
415
416 mailpop3_list(pop3, &msg_tab);
417
418 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
419 struct mailpop3_msg_info * pop3_info;
420 struct mail_flags * flags;
421
422 pop3_info = carray_get(msg_tab, i);
423 if (pop3_info == NULL)
424 continue;
425
426 if (pop3_info->msg_deleted)
427 continue;
428
429 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
430 session, pop3_info->msg_index, &flags);
431 if (r != MAIL_NO_ERROR)
432 continue;
433
434 if (flags->fl_flags & MAIL_FLAG_DELETED) {
435 r = mailpop3_dele(pop3, pop3_info->msg_index);
436 }
437
438 mail_flags_free(flags);
439 }
440
441 mmap_string_free(mmapstr);
442 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
443
444 return MAIL_NO_ERROR;
445
446 close_db_flags:
447 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
448 err:
449 return res;
450}
451
452static int pop3driver_cached_status_folder(mailsession * session,
453 char * mb, uint32_t * result_messages, uint32_t * result_recent,
454 uint32_t * result_unseen)
455{
456 int res;
457 struct pop3_cached_session_state_data * cached_data;
458 char filename_flags[PATH_MAX];
459 struct mail_cache_db * cache_db_flags;
460 MMAPString * mmapstr;
461 unsigned int i;
462 int r;
463 carray * msg_tab;
464 mailpop3 * pop3;
465 uint32_t recent;
466 uint32_t unseen;
467
468 recent = 0;
469 unseen = 0;
470
471 pop3 = get_pop3_session(session);
472
473 cached_data = get_cached_data(session);
474
475 pop3_flags_store_process(cached_data->pop3_flags_directory,
476 cached_data->pop3_flags_store);
477
478 snprintf(filename_flags, PATH_MAX, "%s/%s",
479 cached_data->pop3_flags_directory, FLAGS_NAME);
480
481 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
482 if (r < 0) {
483 res = MAIL_ERROR_MEMORY;
484 goto err;
485 }
486
487 mmapstr = mmap_string_new("");
488 if (mmapstr == NULL) {
489 res = MAIL_ERROR_MEMORY;
490 goto close_db_flags;
491 }
492
493 mailpop3_list(pop3, &msg_tab);
494
495 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
496 struct mailpop3_msg_info * pop3_info;
497 struct mail_flags * flags;
498
499 pop3_info = carray_get(msg_tab, i);
500 if (pop3_info == NULL)
501 continue;
502
503 if (pop3_info->msg_deleted)
504 continue;
505
506 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
507 session, pop3_info->msg_index, &flags);
508 if (r != MAIL_NO_ERROR) {
509 recent ++;
510 unseen ++;
511 continue;
512 }
513
514 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
515 recent ++;
516 }
517 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
518 unseen ++;
519 }
520 mail_flags_free(flags);
521
522 }
523
524 mmap_string_free(mmapstr);
525 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
526
527 * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count;
528 * result_recent = recent;
529 * result_unseen = unseen;
530
531 return MAIL_NO_ERROR;
532
533 close_db_flags:
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535 err:
536 return res;
537}
538
539static int pop3driver_cached_messages_number(mailsession * session,
540 char * mb,
541 uint32_t * result)
542{
543 return mailsession_messages_number(get_ancestor(session), mb, result);
544}
545
546static int pop3driver_cached_recent_number(mailsession * session,
547 char * mb,
548 uint32_t * result)
549{
550 uint32_t messages;
551 uint32_t recent;
552 uint32_t unseen;
553 int r;
554
555 r = pop3driver_cached_status_folder(session, mb,
556 &messages, &recent, &unseen);
557 if (r != MAIL_NO_ERROR)
558 return r;
559
560 * result = recent;
561
562 return MAIL_NO_ERROR;
563}
564
565static int pop3driver_cached_unseen_number(mailsession * session,
566 char * mb,
567 uint32_t * result)
568{
569 uint32_t messages;
570 uint32_t recent;
571 uint32_t unseen;
572 int r;
573
574 r = pop3driver_cached_status_folder(session, mb,
575 &messages, &recent, &unseen);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 * result = unseen;
580
581 return MAIL_NO_ERROR;
582}
583
584/* messages operations */
585
586static int pop3driver_cached_remove_message(mailsession * session,
587 uint32_t num)
588{
589 return mailsession_remove_message(get_ancestor(session), num);
590}
591
592static int
593pop3driver_cached_get_messages_list(mailsession * session,
594 struct mailmessage_list ** result)
595{
596 mailpop3 * pop3;
597
598 pop3 = get_pop3_session(session);
599
600 return pop3_get_messages_list(pop3, session,
601 pop3_cached_message_driver, result);
602}
603
604
605static int
606get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
607 mailsession * session, uint32_t num,
608 struct mailimf_fields ** result)
609{
610 int r;
611 char keyname[PATH_MAX];
612 struct mailpop3_msg_info * info;
613 struct mailimf_fields * fields;
614 int res;
615 mailpop3 * pop3;
616
617 pop3 = get_pop3_session(session);
618
619 r = mailpop3_get_msg_info(pop3, num, &info);
620 switch (r) {
621 case MAILPOP3_ERROR_BAD_STATE:
622 return MAIL_ERROR_BAD_STATE;
623 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
624 return MAIL_ERROR_MSG_NOT_FOUND;
625 case MAILPOP3_NO_ERROR:
626 break;
627 default:
628 return MAIL_ERROR_FETCH;
629 }
630
631 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
632
633 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
634 if (r != MAIL_NO_ERROR) {
635 res = r;
636 goto err;
637 }
638
639 * result = fields;
640
641 return MAIL_NO_ERROR;
642
643 err:
644 return res;
645}
646
647static int
648write_cached_envelope(struct mail_cache_db * cache_db,
649 MMAPString * mmapstr,
650 mailsession * session, uint32_t num,
651 struct mailimf_fields * fields)
652{
653 int r;
654 char keyname[PATH_MAX];
655 int res;
656 struct mailpop3_msg_info * info;
657 mailpop3 * pop3;
658
659 pop3 = get_pop3_session(session);
660
661 r = mailpop3_get_msg_info(pop3, num, &info);
662 switch (r) {
663 case MAILPOP3_ERROR_BAD_STATE:
664 return MAIL_ERROR_BAD_STATE;
665 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
666 return MAIL_ERROR_MSG_NOT_FOUND;
667 case MAILPOP3_NO_ERROR:
668 break;
669 default:
670 return MAIL_ERROR_FETCH;
671 }
672
673 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
674
675 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
676 if (r != MAIL_NO_ERROR) {
677 res = r;
678 goto err;
679 }
680
681 return MAIL_NO_ERROR;
682
683 err:
684 return res;
685}
686
687static void get_uid_from_filename(char * filename)
688{
689 char * p;
690
691 p = strstr(filename, "-header");
692 if (p != NULL)
693 * p = 0;
694}
695
696static int
697pop3driver_cached_get_envelopes_list(mailsession * session,
698 struct mailmessage_list * env_list)
699{
700 int r;
701 unsigned int i;
702 struct pop3_cached_session_state_data * cached_data;
703 char filename_env[PATH_MAX];
704 char filename_flags[PATH_MAX];
705 struct mail_cache_db * cache_db_env;
706 struct mail_cache_db * cache_db_flags;
707 MMAPString * mmapstr;
708 int res;
709
710 cached_data = get_cached_data(session);
711
712 pop3_flags_store_process(cached_data->pop3_flags_directory,
713 cached_data->pop3_flags_store);
714
715 snprintf(filename_env, PATH_MAX, "%s/%s",
716 cached_data->pop3_cache_directory, ENV_NAME);
717
718 mmapstr = mmap_string_new("");
719 if (mmapstr == NULL) {
720 res = MAIL_ERROR_MEMORY;
721 goto err;
722 }
723
724 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
725 if (r < 0) {
726 res = MAIL_ERROR_MEMORY;
727 goto free_mmapstr;
728 }
729
730 snprintf(filename_flags, PATH_MAX, "%s/%s",
731 cached_data->pop3_flags_directory, FLAGS_NAME);
732
733 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
734 if (r < 0) {
735 res = MAIL_ERROR_MEMORY;
736 goto close_db_env;
737 }
738
739 /* fill with cached */
740
741 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
742 mailmessage * msg;
743 struct mailimf_fields * fields;
744 struct mail_flags * flags;
745
746 msg = carray_get(env_list->msg_tab, i);
747
748 if (msg->msg_fields == NULL) {
749 r = get_cached_envelope(cache_db_env, mmapstr,
750 session, msg->msg_index, &fields);
751 if (r == MAIL_NO_ERROR) {
752 msg->msg_cached = TRUE;
753 msg->msg_fields = fields;
754 }
755 }
756
757 if (msg->msg_flags == NULL) {
758 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
759 session, msg->msg_index, &flags);
760 if (r == MAIL_NO_ERROR) {
761 msg->msg_flags = flags;
762 }
763 }
764 }
765
766 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
767 mail_cache_db_close_unlock(filename_env, cache_db_env);
768
769 r = maildriver_generic_get_envelopes_list(session, env_list);
770
771 if (r != MAIL_NO_ERROR) {
772 res = r;
773 goto free_mmapstr;
774 }
775
776 /* add flags */
777
778 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
779 mailmessage * msg;
780
781 msg = carray_get(env_list->msg_tab, i);
782
783 if (msg->msg_flags == NULL)
784 msg->msg_flags = mail_flags_new_empty();
785 }
786
787 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
788 if (r < 0) {
789 res = MAIL_ERROR_MEMORY;
790 goto free_mmapstr;
791 }
792
793 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
794 if (r < 0) {
795 res = MAIL_ERROR_MEMORY;
796 goto close_db_env;
797 }
798
799 /* must write cache */
800
801 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
802 mailmessage * msg;
803
804 msg = carray_get(env_list->msg_tab, i);
805
806 if (msg->msg_fields != NULL) {
807 if (!msg->msg_cached) {
808 r = write_cached_envelope(cache_db_env, mmapstr,
809 session, msg->msg_index, msg->msg_fields);
810 }
811 }
812
813 if (msg->msg_flags != NULL) {
814 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
815 msg->msg_uid, msg->msg_flags);
816 }
817 }
818
819 /* flush cache */
820
821 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
822
823 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
824 mail_cache_db_close_unlock(filename_env, cache_db_env);
825 mmap_string_free(mmapstr);
826
827 /* remove cache files */
828
829 maildriver_message_cache_clean_up(cached_data->pop3_cache_directory,
830 env_list, get_uid_from_filename);
831
832 return MAIL_NO_ERROR;
833
834 close_db_env:
835 mail_cache_db_close_unlock(filename_env, cache_db_env);
836 free_mmapstr:
837 mmap_string_free(mmapstr);
838 err:
839 return res;
840}
841
842static int pop3driver_cached_get_message(mailsession * session,
843 uint32_t num, mailmessage ** result)
844{
845 mailmessage * msg_info;
846 int r;
847
848 msg_info = mailmessage_new();
849 if (msg_info == NULL)
850 return MAIL_ERROR_MEMORY;
851
852 r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0);
853 if (r != MAIL_NO_ERROR) {
854 mailmessage_free(msg_info);
855 return r;
856 }
857
858 * result = msg_info;
859
860 return MAIL_NO_ERROR;
861}
862
863static int pop3driver_cached_get_message_by_uid(mailsession * session,
864 const char * uid, mailmessage ** result)
865{
866 mailpop3 * pop3;
867 struct mailpop3_msg_info * msg_info;
868 int found;
869 unsigned int i;
870
871 if (uid == NULL)
872 return MAIL_ERROR_INVAL;
873
874 pop3 = get_pop3_session(session);
875
876 found = 0;
877
878 /* iterate all messages and look for uid */
879 for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) {
880 msg_info = carray_get(pop3->pop3_msg_tab, i);
881
882 if (msg_info == NULL)
883 continue;
884
885 if (msg_info->msg_deleted)
886 continue;
887
888 /* uid found, stop looking */
889 if (strcmp(msg_info->msg_uidl, uid) == 0) {
890 found = 1;
891 break;
892 }
893 }
894
895 if (!found)
896 return MAIL_ERROR_MSG_NOT_FOUND;
897
898 return pop3driver_cached_get_message(session, msg_info->msg_index, result);
899}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached.h b/libetpan/src/driver/implementation/pop3/pop3driver_cached.h
new file mode 100644
index 0000000..4f4b6c9
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_H
37
38#define POP3DRIVER_CACHED_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45
46extern mailsession_driver * pop3_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
new file mode 100644
index 0000000..4eed0db
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
@@ -0,0 +1,355 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_cached_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "pop3driver.h"
46#include "pop3driver_tools.h"
47#include "pop3driver_cached.h"
48#include "pop3driver_message.h"
49#include "generic_cache.h"
50
51static int pop3_prefetch(mailmessage * msg_info);
52
53static void pop3_prefetch_free(struct generic_message_t * msg);
54
55static int pop3_initialize(mailmessage * msg_info);
56
57static void pop3_flush(mailmessage * msg_info);
58
59static void pop3_check(mailmessage * msg_info);
60
61static int pop3_fetch_header(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int pop3_fetch_size(mailmessage * msg_info,
66 size_t * result);
67
68static int pop3_get_flags(mailmessage * msg_info,
69 struct mail_flags ** result);
70
71static void pop3_uninitialize(mailmessage * msg_info);
72
73static mailmessage_driver local_pop3_cached_message_driver = {
74 .msg_name = "pop3-cached",
75
76 .msg_initialize = pop3_initialize,
77 .msg_uninitialize = pop3_uninitialize,
78
79 .msg_flush = pop3_flush,
80 .msg_check = pop3_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = pop3_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = pop3_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = pop3_get_flags,
96};
97
98mailmessage_driver * pop3_cached_message_driver =
99&local_pop3_cached_message_driver;
100
101
102static inline struct pop3_cached_session_state_data *
103get_cached_session_data(mailmessage * msg)
104{
105 return msg->msg_session->sess_data;
106}
107
108static inline mailsession * get_ancestor_session(mailmessage * msg)
109{
110 return get_cached_session_data(msg)->pop3_ancestor;
111}
112
113static inline struct pop3_session_state_data *
114get_ancestor_session_data(mailmessage * msg)
115{
116 return get_ancestor_session(msg)->sess_data;
117}
118
119static inline mailpop3 * get_pop3_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->pop3_session;
122}
123
124
125static int pop3_prefetch(mailmessage * msg_info)
126{
127 char * msg_content;
128 size_t msg_length;
129 struct generic_message_t * msg;
130 int r;
131 struct pop3_cached_session_state_data * cached_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 snprintf(filename, PATH_MAX, "%s/%s",
139 cached_data->pop3_cache_directory, msg_info->msg_uid);
140
141 r = generic_cache_read(filename, &msg_content, &msg_length);
142 if (r == MAIL_NO_ERROR) {
143 msg = msg_info->msg_data;
144
145 msg->msg_message = msg_content;
146 msg->msg_length = msg_length;
147
148 return MAIL_NO_ERROR;
149 }
150
151 /* we get the message through the network */
152
153 r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index,
154 &msg_content, &msg_length);
155 if (r != MAIL_NO_ERROR)
156 return r;
157
158 /* we write the message cache */
159
160 generic_cache_store(filename, msg_content, msg_length);
161
162 msg = msg_info->msg_data;
163
164 msg->msg_message = msg_content;
165 msg->msg_length = msg_length;
166
167 return MAIL_NO_ERROR;
168}
169
170static void pop3_prefetch_free(struct generic_message_t * msg)
171{
172 if (msg->msg_message != NULL) {
173 mmap_string_unref(msg->msg_message);
174 msg->msg_message = NULL;
175 }
176}
177
178static int pop3_initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182 char * uid;
183 struct mailpop3_msg_info * info;
184 mailpop3 * pop3;
185
186 pop3 = get_pop3_session(msg_info);
187
188 r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
189 switch (r) {
190 case MAILPOP3_NO_ERROR:
191 break;
192 default:
193 return pop3driver_pop3_error_to_mail_error(r);
194 }
195
196 uid = strdup(info->msg_uidl);
197 if (uid == NULL)
198 return MAIL_ERROR_MEMORY;
199
200 r = mailmessage_generic_initialize(msg_info);
201 if (r != MAIL_NO_ERROR) {
202 free(uid);
203 return r;
204 }
205
206 msg = msg_info->msg_data;
207 msg->msg_prefetch = pop3_prefetch;
208 msg->msg_prefetch_free = pop3_prefetch_free;
209 msg_info->msg_uid = uid;
210
211 return MAIL_NO_ERROR;
212}
213
214static void pop3_uninitialize(mailmessage * msg_info)
215{
216 mailmessage_generic_uninitialize(msg_info);
217}
218
219#define FLAGS_NAME "flags.db"
220
221static void pop3_flush(mailmessage * msg_info)
222{
223 mailmessage_generic_flush(msg_info);
224}
225
226static void pop3_check(mailmessage * msg_info)
227{
228 int r;
229
230 if (msg_info->msg_flags != NULL) {
231 r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store,
232 msg_info);
233 }
234}
235
236
237static int pop3_fetch_header(mailmessage * msg_info,
238 char ** result,
239 size_t * result_len)
240{
241 struct generic_message_t * msg;
242 char * headers;
243 size_t headers_length;
244 int r;
245 struct pop3_cached_session_state_data * cached_data;
246 char filename[PATH_MAX];
247
248 msg = msg_info->msg_data;
249
250 if (msg->msg_message != NULL)
251 return mailmessage_generic_fetch_header(msg_info,
252 result, result_len);
253
254 /* we try the cached message */
255
256 cached_data = get_cached_session_data(msg_info);
257
258 snprintf(filename, PATH_MAX, "%s/%s-header",
259 cached_data->pop3_cache_directory, msg_info->msg_uid);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message trough the network */
270
271 r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 generic_cache_store(filename, headers, headers_length);
277
278 * result = headers;
279 * result_len = headers_length;
280
281 return MAIL_NO_ERROR;
282}
283
284static int pop3_fetch_size(mailmessage * msg_info,
285 size_t * result)
286{
287 return pop3driver_size(get_ancestor_session(msg_info),
288 msg_info->msg_index, result);
289}
290
291static int pop3_get_flags(mailmessage * msg_info,
292 struct mail_flags ** result)
293{
294 int r;
295 struct mail_flags * flags;
296 struct mail_cache_db * cache_db_flags;
297 char filename_flags[PATH_MAX];
298 int res;
299 struct pop3_cached_session_state_data * cached_data;
300 MMAPString * mmapstr;
301
302 if (msg_info->msg_flags != NULL) {
303 * result = msg_info->msg_flags;
304
305 return MAIL_NO_ERROR;
306 }
307
308 cached_data = get_cached_session_data(msg_info);
309
310 flags = mail_flags_store_get(cached_data->pop3_flags_store,
311 msg_info->msg_index);
312
313 if (flags == NULL) {
314 snprintf(filename_flags, PATH_MAX, "%s/%s",
315 cached_data->pop3_flags_directory, FLAGS_NAME);
316
317 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
318 if (r < 0) {
319 res = MAIL_ERROR_MEMORY;
320 goto err;
321 }
322
323 mmapstr = mmap_string_new("");
324 if (mmapstr == NULL) {
325 res = MAIL_ERROR_MEMORY;
326 goto close_db_flags;
327 }
328
329 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
330 msg_info->msg_session, msg_info->msg_index, &flags);
331 if (r != MAIL_NO_ERROR) {
332 flags = mail_flags_new_empty();
333 if (flags == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto free_mmapstr;
336 }
337 }
338
339 mmap_string_free(mmapstr);
340 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
341 }
342
343 msg_info->msg_flags = flags;
344
345 * result = flags;
346
347 return MAIL_NO_ERROR;
348
349 free_mmapstr:
350 mmap_string_free(mmapstr);
351 close_db_flags:
352 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
353 err:
354 return res;
355}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h
new file mode 100644
index 0000000..f13cec7
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_CACHED_MESSAGE_H
37
38#define POP3DRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_message.c b/libetpan/src/driver/implementation/pop3/pop3driver_message.c
new file mode 100644
index 0000000..6ea8979
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_message.c
@@ -0,0 +1,193 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_message.h"
37
38#include "mailmessage_tools.h"
39#include "pop3driver_tools.h"
40#include "pop3driver.h"
41#include "mailpop3.h"
42#include <stdlib.h>
43#include <string.h>
44
45static int pop3_prefetch(mailmessage * msg_info);
46
47static void pop3_prefetch_free(struct generic_message_t * msg);
48
49static int pop3_initialize(mailmessage * msg_info);
50
51static int pop3_fetch_header(mailmessage * msg_info,
52 char ** result,
53 size_t * result_len);
54
55static int pop3_fetch_size(mailmessage * msg_info,
56 size_t * result);
57
58static mailmessage_driver local_pop3_message_driver = {
59 .msg_name = "pop3",
60
61 .msg_initialize = pop3_initialize,
62 .msg_uninitialize = mailmessage_generic_uninitialize,
63
64 .msg_flush = mailmessage_generic_flush,
65 .msg_check = NULL,
66
67 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
68
69 .msg_fetch = mailmessage_generic_fetch,
70 .msg_fetch_header = pop3_fetch_header,
71 .msg_fetch_body = mailmessage_generic_fetch_body,
72 .msg_fetch_size = pop3_fetch_size,
73 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
74 .msg_fetch_section = mailmessage_generic_fetch_section,
75 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
76 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
77 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
78 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
79
80 .msg_get_flags = NULL,
81};
82
83mailmessage_driver * pop3_message_driver = &local_pop3_message_driver;
84
85static inline struct pop3_session_state_data *
86get_data(mailsession * session)
87{
88 return session->sess_data;
89}
90
91
92static mailpop3 * get_pop3_session(mailsession * session)
93{
94 return get_data(session)->pop3_session;
95}
96
97
98static int pop3_prefetch(mailmessage * msg_info)
99{
100 char * msg_content;
101 size_t msg_length;
102 struct generic_message_t * msg;
103 int r;
104
105 r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index,
106 &msg_content, &msg_length);
107 if (r != MAIL_NO_ERROR)
108 return r;
109
110 msg = msg_info->msg_data;
111
112 msg->msg_message = msg_content;
113 msg->msg_length = msg_length;
114
115 return MAIL_NO_ERROR;
116}
117
118static void pop3_prefetch_free(struct generic_message_t * msg)
119{
120 if (msg->msg_message != NULL) {
121 mmap_string_unref(msg->msg_message);
122 msg->msg_message = NULL;
123 }
124}
125
126static int pop3_initialize(mailmessage * msg_info)
127{
128 struct generic_message_t * msg;
129 int r;
130 char * uid;
131 struct mailpop3_msg_info * info;
132 mailpop3 * pop3;
133
134 pop3 = get_pop3_session(msg_info->msg_session);
135
136 r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
137 switch (r) {
138 case MAILPOP3_NO_ERROR:
139 break;
140 default:
141 return pop3driver_pop3_error_to_mail_error(r);
142 }
143
144 uid = strdup(info->msg_uidl);
145 if (uid == NULL)
146 return MAIL_ERROR_MEMORY;
147
148 r = mailmessage_generic_initialize(msg_info);
149 if (r != MAIL_NO_ERROR) {
150 free(uid);
151 return r;
152 }
153
154 msg = msg_info->msg_data;
155 msg->msg_prefetch = pop3_prefetch;
156 msg->msg_prefetch_free = pop3_prefetch_free;
157 msg_info->msg_uid = uid;
158
159 return MAIL_NO_ERROR;
160}
161
162
163static int pop3_fetch_header(mailmessage * msg_info,
164 char ** result,
165 size_t * result_len)
166{
167 struct generic_message_t * msg;
168 char * headers;
169 size_t headers_length;
170 int r;
171
172 msg = msg_info->msg_data;
173
174 if (msg->msg_message != NULL)
175 return mailmessage_generic_fetch_header(msg_info,
176 result, result_len);
177
178 r = pop3driver_header(msg_info->msg_session, msg_info->msg_index,
179 &headers, &headers_length);
180 if (r != MAIL_NO_ERROR)
181 return r;
182
183 * result = headers;
184 * result_len = headers_length;
185
186 return MAIL_NO_ERROR;
187}
188
189static int pop3_fetch_size(mailmessage * msg_info,
190 size_t * result)
191{
192 return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result);
193}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_message.h b/libetpan/src/driver/implementation/pop3/pop3driver_message.h
new file mode 100644
index 0000000..ad0a01b
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_MESSAGE_H
37
38#define POP3DRIVER_MESSAGE_H
39
40#include <libetpan/pop3driver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * pop3_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_tools.c b/libetpan/src/driver/implementation/pop3/pop3driver_tools.c
new file mode 100644
index 0000000..73dd22a
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_tools.c
@@ -0,0 +1,344 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3driver_tools.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42
43#include "maildriver_types.h"
44#include "mailpop3.h"
45#include "pop3driver.h"
46#include "pop3driver_cached.h"
47#include "generic_cache.h"
48#include "imfcache.h"
49#include "mailmessage.h"
50#include "mail_cache_db.h"
51
52int pop3driver_pop3_error_to_mail_error(int error)
53{
54 switch (error) {
55 case MAILPOP3_NO_ERROR:
56 return MAIL_NO_ERROR;
57
58 case MAILPOP3_ERROR_BAD_STATE:
59 return MAIL_ERROR_BAD_STATE;
60
61 case MAILPOP3_ERROR_UNAUTHORIZED:
62 return MAIL_ERROR_CONNECT;
63
64 case MAILPOP3_ERROR_STREAM:
65 return MAIL_ERROR_STREAM;
66
67 case MAILPOP3_ERROR_DENIED:
68 return MAIL_ERROR_CONNECT;
69
70 case MAILPOP3_ERROR_BAD_USER:
71 case MAILPOP3_ERROR_BAD_PASSWORD:
72 return MAIL_ERROR_LOGIN;
73
74 case MAILPOP3_ERROR_CANT_LIST:
75 return MAIL_ERROR_LIST;
76
77 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
78 return MAIL_ERROR_MSG_NOT_FOUND;
79
80 case MAILPOP3_ERROR_MEMORY:
81 return MAIL_ERROR_MEMORY;
82
83 case MAILPOP3_ERROR_CONNECTION_REFUSED:
84 return MAIL_ERROR_CONNECT;
85
86 case MAILPOP3_ERROR_APOP_NOT_SUPPORTED:
87 return MAIL_ERROR_NO_APOP;
88
89 case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED:
90 return MAIL_ERROR_CAPABILITY;
91
92 case MAILPOP3_ERROR_STLS_NOT_SUPPORTED:
93 return MAIL_ERROR_NO_TLS;
94
95 default:
96 return MAIL_ERROR_INVAL;
97 }
98};
99
100static inline struct pop3_session_state_data *
101session_get_data(mailsession * session)
102{
103 return session->sess_data;
104}
105
106static inline mailpop3 * session_get_pop3_session(mailsession * session)
107{
108 return session_get_data(session)->pop3_session;
109}
110
111static inline struct pop3_cached_session_state_data *
112cached_session_get_data(mailsession * session)
113{
114 return session->sess_data;
115}
116
117static inline mailsession *
118cached_session_get_ancestor(mailsession * session)
119{
120 return cached_session_get_data(session)->pop3_ancestor;
121}
122
123static inline struct pop3_session_state_data *
124cached_session_get_ancestor_data(mailsession * session)
125{
126 return session_get_data(cached_session_get_ancestor(session));
127}
128
129static inline mailpop3 *
130cached_session_get_pop3_session(mailsession * session)
131{
132 return session_get_pop3_session(cached_session_get_ancestor(session));
133}
134
135
136int pop3driver_retr(mailsession * session, uint32_t index,
137 char ** result, size_t * result_len)
138{
139 char * msg_content;
140 size_t msg_length;
141 int r;
142
143 r = mailpop3_retr(session_get_pop3_session(session), index,
144 &msg_content, &msg_length);
145
146 switch (r) {
147 case MAILPOP3_NO_ERROR:
148 break;
149 default:
150 return pop3driver_pop3_error_to_mail_error(r);
151 }
152
153 * result = msg_content;
154 * result_len = msg_length;
155
156 return MAIL_NO_ERROR;
157}
158
159int pop3driver_header(mailsession * session, uint32_t index,
160 char ** result,
161 size_t * result_len)
162{
163 char * headers;
164 size_t headers_length;
165 int r;
166
167 r = mailpop3_header(session_get_pop3_session(session),
168 index, &headers, &headers_length);
169
170 switch (r) {
171 case MAILPOP3_NO_ERROR:
172 break;
173 default:
174 return pop3driver_pop3_error_to_mail_error(r);
175 }
176
177 * result = headers;
178 * result_len = headers_length;
179
180 return MAIL_NO_ERROR;
181}
182
183int pop3driver_size(mailsession * session, uint32_t index,
184 size_t * result)
185{
186 mailpop3 * pop3;
187 carray * msg_tab;
188 struct mailpop3_msg_info * info;
189 int r;
190
191 pop3 = session_get_pop3_session(session);
192
193 mailpop3_list(pop3, &msg_tab);
194
195 r = mailpop3_get_msg_info(pop3, index, &info);
196 switch (r) {
197 case MAILPOP3_NO_ERROR:
198 break;
199 default:
200 return pop3driver_pop3_error_to_mail_error(r);
201 }
202
203 * result = info->msg_size;
204
205 return MAIL_NO_ERROR;
206}
207
208int
209pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
210 MMAPString * mmapstr,
211 mailsession * session,
212 uint32_t num,
213 struct mail_flags ** result)
214{
215 int r;
216 char keyname[PATH_MAX];
217 struct mail_flags * flags;
218 int res;
219 struct mailpop3_msg_info * info;
220
221 r = mailpop3_get_msg_info(cached_session_get_pop3_session(session),
222 num, &info);
223 switch (r) {
224 case MAILPOP3_ERROR_BAD_STATE:
225 return MAIL_ERROR_BAD_STATE;
226 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
227 return MAIL_ERROR_MSG_NOT_FOUND;
228 case MAILPOP3_NO_ERROR:
229 break;
230 default:
231 return MAIL_ERROR_FETCH;
232 }
233
234 snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl);
235
236 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
237 if (r != MAIL_NO_ERROR) {
238 res = r;
239 goto err;
240 }
241
242 * result = flags;
243
244 return MAIL_NO_ERROR;
245
246 err:
247 return res;
248}
249
250int
251pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
252 MMAPString * mmapstr,
253 char * uid,
254 struct mail_flags * flags)
255{
256 int r;
257 char keyname[PATH_MAX];
258 int res;
259
260 snprintf(keyname, PATH_MAX, "%s-flags", uid);
261
262 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
263 if (r != MAIL_NO_ERROR) {
264 res = r;
265 goto err;
266 }
267
268 return MAIL_NO_ERROR;
269
270 err:
271 return res;
272}
273
274int pop3_get_messages_list(mailpop3 * pop3,
275 mailsession * session,
276 mailmessage_driver * driver,
277 struct mailmessage_list ** result)
278{
279 carray * msg_tab;
280 carray * tab;
281 struct mailmessage_list * env_list;
282 unsigned int i;
283 int res;
284 int r;
285
286 mailpop3_list(pop3, &msg_tab);
287
288 tab = carray_new(128);
289 if (tab == NULL) {
290 res = MAIL_ERROR_MEMORY;
291 goto err;
292 }
293
294 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
295 struct mailpop3_msg_info * pop3_info;
296 mailmessage * msg;
297
298 pop3_info = carray_get(msg_tab, i);
299
300 if (pop3_info == NULL)
301 continue;
302
303 if (pop3_info->msg_deleted)
304 continue;
305
306 msg = mailmessage_new();
307 if (msg == NULL) {
308 res = MAIL_ERROR_MEMORY;
309 goto free_list;
310 }
311
312 r = mailmessage_init(msg, session, driver,
313 (uint32_t) pop3_info->msg_index, pop3_info->msg_size);
314 if (r != MAIL_NO_ERROR) {
315 mailmessage_free(msg);
316 res = r;
317 goto free_list;
318 }
319
320 r = carray_add(tab, msg, NULL);
321 if (r < 0) {
322 mailmessage_free(msg);
323 res = MAIL_ERROR_MEMORY;
324 goto free_list;
325 }
326 }
327
328 env_list = mailmessage_list_new(/*list*/ tab);
329 if (env_list == NULL) {
330 res = MAIL_ERROR_MEMORY;
331 goto free_list;
332 }
333
334 * result = env_list;
335
336 return MAIL_NO_ERROR;
337
338 free_list:
339 for(i = 0 ; i < carray_count(tab) ; i ++)
340 mailmessage_free(carray_get(tab, i));
341 carray_free(tab);
342 err:
343 return res;
344}
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_tools.h b/libetpan/src/driver/implementation/pop3/pop3driver_tools.h
new file mode 100644
index 0000000..e6413aa
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_tools.h
@@ -0,0 +1,82 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_TOOLS_H
37
38#define POP3DRIVER_TOOLS_H
39
40#include "mail_cache_db_types.h"
41#include "pop3driver_types.h"
42#include "mailpop3.h"
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48int pop3driver_pop3_error_to_mail_error(int error);
49
50int pop3driver_retr(mailsession * session, uint32_t index,
51 char ** result, size_t * result_len);
52
53int pop3driver_header(mailsession * session, uint32_t index,
54 char ** result,
55 size_t * result_len);
56
57int pop3driver_size(mailsession * session, uint32_t index,
58 size_t * result);
59
60int
61pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
62 MMAPString * mmapstr,
63 mailsession * session,
64 uint32_t num,
65 struct mail_flags ** result);
66
67int
68pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
69 MMAPString * mmapstr,
70 char * uid,
71 struct mail_flags * flags);
72
73int pop3_get_messages_list(mailpop3 * pop3,
74 mailsession * session,
75 mailmessage_driver * driver,
76 struct mailmessage_list ** result);
77
78#ifdef __cplusplus
79}
80#endif
81
82#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_types.h b/libetpan/src/driver/implementation/pop3/pop3driver_types.h
new file mode 100644
index 0000000..4bb872c
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_types.h
@@ -0,0 +1,153 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3DRIVER_TYPES_H
37
38#define POP3DRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/maildriver_types.h>
43#include <libetpan/mailpop3.h>
44#include <libetpan/maildriver_types.h>
45#include <libetpan/chash.h>
46#include <libetpan/mailstorage_types.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52/* POP3 driver for session */
53
54enum {
55 POP3DRIVER_SET_AUTH_TYPE = 1,
56};
57
58enum {
59 POP3DRIVER_AUTH_TYPE_PLAIN = 0,
60 POP3DRIVER_AUTH_TYPE_APOP,
61 POP3DRIVER_AUTH_TYPE_TRY_APOP,
62};
63
64struct pop3_session_state_data {
65 int pop3_auth_type;
66 mailpop3 * pop3_session;
67};
68
69/* cached POP3 driver for session */
70
71enum {
72 /* the mapping of the parameters should be the same as for pop3 */
73 POP3DRIVER_CACHED_SET_AUTH_TYPE = 1,
74 /* cache specific */
75 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
76 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
77};
78
79struct pop3_cached_session_state_data {
80 mailsession * pop3_ancestor;
81 char pop3_cache_directory[PATH_MAX];
82 char pop3_flags_directory[PATH_MAX];
83 chash * pop3_flags_hash;
84 carray * pop3_flags_array;
85 struct mail_flags_store * pop3_flags_store;
86};
87
88/* pop3 storage */
89
90/*
91 pop3_mailstorage is the state data specific to the POP3 storage.
92
93 - servername this is the name of the POP3 server
94
95 - port is the port to connect to, on the server.
96 you give 0 to use the default port.
97
98 - connection_type is the type of socket layer to use.
99 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
100 CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS.
101
102 - auth_type is the authenticate mechanism to use.
103 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
104 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
105
106 - login is the login of the POP3 account.
107
108 - password is the password of the POP3 account.
109
110 - cached if this value is != 0, a persistant cache will be
111 stored on local system.
112
113 - cache_directory is the location of the cache.
114
115 - flags_directory is the location of the flags.
116*/
117
118struct pop3_mailstorage {
119 char * pop3_servername;
120 uint16_t pop3_port;
121 char * pop3_command;
122 int pop3_connection_type;
123
124 int pop3_auth_type;
125 char * pop3_login;
126 char * pop3_password;
127
128 int pop3_cached;
129 char * pop3_cache_directory;
130 char * pop3_flags_directory;
131};
132
133/* this is the type of POP3 authentication */
134
135enum {
136 POP3_AUTH_TYPE_PLAIN, /* plain text authentication */
137 POP3_AUTH_TYPE_APOP, /* APOP authentication */
138 POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails,
139 try plain text */
140 POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
141 POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
142 POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
143 POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
144 POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
145 POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
146 POP3_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
147};
148
149#ifdef __cplusplus
150}
151#endif
152
153#endif
diff --git a/libetpan/src/driver/implementation/pop3/pop3storage.c b/libetpan/src/driver/implementation/pop3/pop3storage.c
new file mode 100644
index 0000000..1cff650
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3storage.c
@@ -0,0 +1,284 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "pop3storage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "mail.h"
42#include "mailstorage_tools.h"
43#include "maildriver.h"
44
45/* pop3 storage */
46
47#define POP3_DEFAULT_PORT 110
48#define POP3S_DEFAULT_PORT 995
49
50static int pop3_mailstorage_connect(struct mailstorage * storage);
51static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
52 char * pathname, mailsession ** result);
53static void pop3_mailstorage_uninitialize(struct mailstorage * storage);
54
55static mailstorage_driver pop3_mailstorage_driver = {
56 .sto_name = "pop3",
57 .sto_connect = pop3_mailstorage_connect,
58 .sto_get_folder_session = pop3_mailstorage_get_folder_session,
59 .sto_uninitialize = pop3_mailstorage_uninitialize,
60};
61
62int pop3_mailstorage_init(struct mailstorage * storage,
63 char * pop3_servername, uint16_t pop3_port,
64 char * pop3_command,
65 int pop3_connection_type, int pop3_auth_type,
66 char * pop3_login, char * pop3_password,
67 int pop3_cached, char * pop3_cache_directory, char * pop3_flags_directory)
68{
69 struct pop3_mailstorage * pop3_storage;
70
71 pop3_storage = malloc(sizeof(* pop3_storage));
72 if (pop3_storage == NULL)
73 goto err;
74
75 pop3_storage->pop3_servername = strdup(pop3_servername);
76 if (pop3_storage->pop3_servername == NULL)
77 goto free;
78
79 pop3_storage->pop3_connection_type = pop3_connection_type;
80
81 if (pop3_port == 0) {
82 switch (pop3_connection_type) {
83 case CONNECTION_TYPE_PLAIN:
84 case CONNECTION_TYPE_TRY_STARTTLS:
85 case CONNECTION_TYPE_STARTTLS:
86 case CONNECTION_TYPE_COMMAND:
87 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
88 case CONNECTION_TYPE_COMMAND_STARTTLS:
89 pop3_port = POP3_DEFAULT_PORT;
90 break;
91
92 case CONNECTION_TYPE_TLS:
93 case CONNECTION_TYPE_COMMAND_TLS:
94 pop3_port = POP3S_DEFAULT_PORT;
95 break;
96 }
97 }
98
99 pop3_storage->pop3_port = pop3_port;
100
101 if (pop3_command != NULL) {
102 pop3_storage->pop3_command = strdup(pop3_command);
103 if (pop3_storage->pop3_command == NULL)
104 goto free_servername;
105 }
106 else
107 pop3_storage->pop3_command = NULL;
108
109 pop3_storage->pop3_auth_type = pop3_auth_type;
110
111 if (pop3_login != NULL) {
112 pop3_storage->pop3_login = strdup(pop3_login);
113 if (pop3_storage->pop3_login == NULL)
114 goto free_command;
115 }
116 else
117 pop3_storage->pop3_login = NULL;
118
119 if (pop3_password != NULL) {
120 pop3_storage->pop3_password = strdup(pop3_password);
121 if (pop3_storage->pop3_password == NULL)
122 goto free_login;
123 }
124 else
125 pop3_storage->pop3_password = NULL;
126
127 pop3_storage->pop3_cached = pop3_cached;
128
129 if (pop3_cached && (pop3_cache_directory != NULL) &&
130 (pop3_flags_directory != NULL)) {
131 pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory);
132 if (pop3_storage->pop3_cache_directory == NULL)
133 goto free_password;
134 pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory);
135 if (pop3_storage->pop3_flags_directory == NULL)
136 goto free_cache_directory;
137 }
138 else {
139 pop3_storage->pop3_cached = FALSE;
140 pop3_storage->pop3_cache_directory = NULL;
141 pop3_storage->pop3_flags_directory = NULL;
142 }
143
144 storage->sto_data = pop3_storage;
145 storage->sto_driver = &pop3_mailstorage_driver;
146
147 return MAIL_NO_ERROR;
148
149 free_cache_directory:
150 free(pop3_storage->pop3_cache_directory);
151 free_password:
152 if (pop3_storage->pop3_password != NULL)
153 free(pop3_storage->pop3_password);
154 free_login:
155 if (pop3_storage->pop3_login != NULL)
156 free(pop3_storage->pop3_login);
157 free_command:
158 if (pop3_storage->pop3_command != NULL)
159 free(pop3_storage->pop3_command);
160 free_servername:
161 if (pop3_storage->pop3_servername != NULL)
162 free(pop3_storage->pop3_servername);
163 free:
164 free(pop3_storage);
165 err:
166 return MAIL_ERROR_MEMORY;
167}
168
169static void pop3_mailstorage_uninitialize(struct mailstorage * storage)
170{
171 struct pop3_mailstorage * pop3_storage;
172
173 pop3_storage = storage->sto_data;
174
175 if (pop3_storage->pop3_flags_directory != NULL)
176 free(pop3_storage->pop3_flags_directory);
177 if (pop3_storage->pop3_cache_directory != NULL)
178 free(pop3_storage->pop3_cache_directory);
179 if (pop3_storage->pop3_password != NULL)
180 free(pop3_storage->pop3_password);
181 if (pop3_storage->pop3_login != NULL)
182 free(pop3_storage->pop3_login);
183 if (pop3_storage->pop3_command != NULL)
184 free(pop3_storage->pop3_command);
185 free(pop3_storage->pop3_servername);
186 free(pop3_storage);
187
188 storage->sto_data = pop3_storage;
189}
190
191static int pop3_mailstorage_connect(struct mailstorage * storage)
192{
193 struct pop3_mailstorage * pop3_storage;
194 mailsession_driver * driver;
195 int r;
196 int res;
197 mailsession * session;
198 int auth_type;
199
200 pop3_storage = storage->sto_data;
201
202 if (pop3_storage->pop3_cached)
203 driver = pop3_cached_session_driver;
204 else
205 driver = pop3_session_driver;
206
207 r = mailstorage_generic_connect(driver,
208 pop3_storage->pop3_servername,
209 pop3_storage->pop3_port, pop3_storage->pop3_command,
210 pop3_storage->pop3_connection_type,
211 POP3DRIVER_CACHED_SET_CACHE_DIRECTORY,
212 pop3_storage->pop3_cache_directory,
213 POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY,
214 pop3_storage->pop3_flags_directory,
215 &session);
216 switch (r) {
217 case MAIL_NO_ERROR_NON_AUTHENTICATED:
218 case MAIL_NO_ERROR_AUTHENTICATED:
219 case MAIL_NO_ERROR:
220 break;
221 default:
222 res = r;
223 goto err;
224 }
225
226 auth_type = -1;
227 switch (pop3_storage->pop3_auth_type) {
228 case POP3_AUTH_TYPE_PLAIN:
229 auth_type = POP3DRIVER_AUTH_TYPE_PLAIN;
230 break;
231 case POP3_AUTH_TYPE_APOP:
232 auth_type = POP3DRIVER_AUTH_TYPE_APOP;
233 break;
234 case POP3_AUTH_TYPE_TRY_APOP:
235 auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP;
236 break;
237 }
238
239 if (auth_type != -1) {
240 mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type);
241 }
242
243 r = mailstorage_generic_auth(session, r,
244 pop3_storage->pop3_auth_type,
245 pop3_storage->pop3_login,
246 pop3_storage->pop3_password);
247 if (r != MAIL_NO_ERROR) {
248 if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) {
249 /* try in clear authentication */
250 mailsession_free(session);
251
252 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN;
253 r = mailstorage_connect(storage);
254 if (r != MAIL_NO_ERROR) {
255 res = r;
256 return res;
257 }
258 pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP;
259
260 return MAIL_NO_ERROR;
261 }
262
263 res = r;
264 goto free;
265 }
266
267 storage->sto_session = session;
268
269 return MAIL_NO_ERROR;
270
271 free:
272 mailsession_free(session);
273 err:
274 return res;
275}
276
277static int pop3_mailstorage_get_folder_session(struct mailstorage * storage,
278 char * pathname, mailsession ** result)
279{
280 * result = storage->sto_session;
281
282 return MAIL_NO_ERROR;
283}
284
diff --git a/libetpan/src/driver/implementation/pop3/pop3storage.h b/libetpan/src/driver/implementation/pop3/pop3storage.h
new file mode 100644
index 0000000..e8cd513
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3storage.h
@@ -0,0 +1,95 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef POP3STORAGE_H
37
38#define POP3STORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/pop3driver_types.h>
45#include <libetpan/pop3driver.h>
46#include <libetpan/pop3driver_cached.h>
47
48/*
49 pop3_mailstorage_init is the constructor for a POP3 storage
50
51 @param storage this is the storage to initialize.
52
53 @param servername this is the name of the POP3 server
54
55 @param port is the port to connect to, on the server.
56 you give 0 to use the default port.
57
58 @param command the command used to connect to the server instead of
59 allowing normal TCP connections to be used.
60
61 @param connection_type is the type of socket layer to use.
62 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
63 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
64 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
65 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
66
67 @param auth_type is the authenticate mechanism to use.
68 The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP
69 or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented.
70
71 @param login is the login of the POP3 account.
72
73 @param password is the password of the POP3 account.
74
75 @param cached if this value is != 0, a persistant cache will be
76 stored on local system.
77
78 @param cache_directory is the location of the cache
79
80 @param flags_directory is the location of the flags
81*/
82
83int pop3_mailstorage_init(struct mailstorage * storage,
84 char * pop3_servername, uint16_t pop3_port,
85 char * pop3_command,
86 int pop3_connection_type, int pop3_auth_type,
87 char * pop3_login, char * pop3_password,
88 int pop3_cached, char * pop3_cache_directory,
89 char * pop3_flags_directory);
90
91#ifdef __cplusplus
92}
93#endif
94
95#endif
diff --git a/libetpan/src/driver/interface/maildriver.c b/libetpan/src/driver/interface/maildriver.c
new file mode 100644
index 0000000..5b6c4f2
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver.c
@@ -0,0 +1,383 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver.h"
37#include <ctype.h>
38#include <string.h>
39#include <stdlib.h>
40
41/* *********************************************************************** */
42/* mail session */
43
44mailsession * mailsession_new(mailsession_driver * sess_driver)
45{
46 mailsession * session;
47 int r;
48
49 session = malloc(sizeof(* session));
50
51 session->sess_data = NULL;
52
53 if (sess_driver->sess_initialize != NULL) {
54 r = sess_driver->sess_initialize(session);
55 if (r != MAIL_NO_ERROR)
56 goto free;
57 }
58
59 session->sess_driver = sess_driver;
60
61 return session;
62
63 free:
64 free(session);
65 return NULL;
66}
67
68void mailsession_free(mailsession * session)
69{
70 if (session->sess_driver->sess_uninitialize != NULL)
71 session->sess_driver->sess_uninitialize(session);
72 free(session);
73}
74
75int mailsession_parameters(mailsession * session,
76 int id, void * value)
77{
78 if (session->sess_driver->sess_parameters == NULL)
79 return MAIL_ERROR_NOT_IMPLEMENTED;
80
81 return session->sess_driver->sess_parameters(session, id, value);
82}
83
84int mailsession_connect_stream(mailsession * session, mailstream * s)
85{
86 if (session->sess_driver->sess_connect_stream == NULL)
87 return MAIL_ERROR_NOT_IMPLEMENTED;
88
89 return session->sess_driver->sess_connect_stream(session, s);
90}
91
92int mailsession_connect_path(mailsession * session, char * path)
93{
94 if (session->sess_driver->sess_connect_path == NULL)
95 return MAIL_ERROR_NOT_IMPLEMENTED;
96
97 return session->sess_driver->sess_connect_path(session, path);
98}
99
100int mailsession_starttls(mailsession * session)
101{
102 if (session->sess_driver->sess_starttls == NULL)
103 return MAIL_ERROR_NOT_IMPLEMENTED;
104
105 return session->sess_driver->sess_starttls(session);
106}
107
108int mailsession_login(mailsession * session,
109 char * userid, char * password)
110{
111 if (session->sess_driver->sess_login == NULL)
112 return MAIL_ERROR_NOT_IMPLEMENTED;
113
114 return session->sess_driver->sess_login(session, userid, password);
115}
116
117int mailsession_logout(mailsession * session)
118{
119 if (session->sess_driver->sess_logout == NULL)
120 return MAIL_ERROR_NOT_IMPLEMENTED;
121
122 return session->sess_driver->sess_logout(session);
123}
124
125int mailsession_noop(mailsession * session)
126{
127 if (session->sess_driver->sess_noop == NULL)
128 return MAIL_ERROR_NOT_IMPLEMENTED;
129
130 return session->sess_driver->sess_noop(session);
131}
132
133/* folders operations */
134
135int mailsession_build_folder_name(mailsession * session, char * mb,
136 char * name, char ** result)
137{
138 if (session->sess_driver->sess_build_folder_name == NULL)
139 return MAIL_ERROR_NOT_IMPLEMENTED;
140
141 return session->sess_driver->sess_build_folder_name(session,
142 mb, name, result);
143}
144
145int mailsession_create_folder(mailsession * session, char * mb)
146{
147 if (session->sess_driver->sess_create_folder == NULL)
148 return MAIL_ERROR_NOT_IMPLEMENTED;
149
150 return session->sess_driver->sess_create_folder(session, mb);
151}
152
153int mailsession_delete_folder(mailsession * session, char * mb)
154{
155 if (session->sess_driver->sess_delete_folder == NULL)
156 return MAIL_ERROR_NOT_IMPLEMENTED;
157
158 return session->sess_driver->sess_delete_folder(session, mb);
159}
160
161int mailsession_rename_folder(mailsession * session,
162 char * mb, char * new_name)
163{
164 if (session->sess_driver->sess_rename_folder == NULL)
165 return MAIL_ERROR_NOT_IMPLEMENTED;
166
167 return session->sess_driver->sess_rename_folder(session, mb, new_name);
168}
169
170int mailsession_check_folder(mailsession * session)
171{
172 if (session->sess_driver->sess_check_folder == NULL)
173 return MAIL_ERROR_NOT_IMPLEMENTED;
174
175 return session->sess_driver->sess_check_folder(session);
176}
177
178int mailsession_examine_folder(mailsession * session, char * mb)
179{
180 if (session->sess_driver->sess_examine_folder == NULL)
181 return MAIL_ERROR_NOT_IMPLEMENTED;
182
183 return session->sess_driver->sess_examine_folder(session, mb);
184}
185
186int mailsession_select_folder(mailsession * session, char * mb)
187{
188 if (session->sess_driver->sess_select_folder == NULL)
189 return MAIL_ERROR_NOT_IMPLEMENTED;
190
191 return session->sess_driver->sess_select_folder(session, mb);
192}
193
194int mailsession_expunge_folder(mailsession * session)
195{
196 if (session->sess_driver->sess_expunge_folder == NULL)
197 return MAIL_ERROR_NOT_IMPLEMENTED;
198
199 return session->sess_driver->sess_expunge_folder(session);
200}
201
202int mailsession_status_folder(mailsession * session, char * mb,
203 uint32_t * result_messages, uint32_t * result_recent,
204 uint32_t * result_unseen)
205{
206 if (session->sess_driver->sess_status_folder == NULL)
207 return MAIL_ERROR_NOT_IMPLEMENTED;
208
209 return session->sess_driver->sess_status_folder(session, mb,
210 result_messages, result_recent, result_unseen);
211}
212
213int mailsession_messages_number(mailsession * session, char * mb,
214 uint32_t * result)
215{
216 if (session->sess_driver->sess_messages_number == NULL)
217 return MAIL_ERROR_NOT_IMPLEMENTED;
218
219 return session->sess_driver->sess_messages_number(session, mb, result);
220}
221
222int mailsession_recent_number(mailsession * session, char * mb,
223 uint32_t * result)
224{
225 if (session->sess_driver->sess_recent_number == NULL)
226 return MAIL_ERROR_NOT_IMPLEMENTED;
227
228 return session->sess_driver->sess_recent_number(session, mb, result);
229}
230
231int mailsession_unseen_number(mailsession * session, char * mb,
232 uint32_t * result)
233{
234 if (session->sess_driver->sess_unseen_number == NULL)
235 return MAIL_ERROR_NOT_IMPLEMENTED;
236
237 return session->sess_driver->sess_recent_number(session, mb, result);
238}
239
240int mailsession_list_folders(mailsession * session, char * mb,
241 struct mail_list ** result)
242{
243 if (session->sess_driver->sess_list_folders == NULL)
244 return MAIL_ERROR_NOT_IMPLEMENTED;
245
246 return session->sess_driver->sess_list_folders(session, mb, result);
247}
248
249int mailsession_lsub_folders(mailsession * session, char * mb,
250 struct mail_list ** result)
251{
252 if (session->sess_driver->sess_lsub_folders == NULL)
253 return MAIL_ERROR_NOT_IMPLEMENTED;
254
255 return session->sess_driver->sess_lsub_folders(session, mb, result);
256}
257
258int mailsession_subscribe_folder(mailsession * session, char * mb)
259{
260 if (session->sess_driver->sess_subscribe_folder == NULL)
261 return MAIL_ERROR_NOT_IMPLEMENTED;
262
263 return session->sess_driver->sess_subscribe_folder(session, mb);
264}
265
266int mailsession_unsubscribe_folder(mailsession * session, char * mb)
267{
268 if (session->sess_driver->sess_unsubscribe_folder == NULL)
269 return MAIL_ERROR_NOT_IMPLEMENTED;
270
271 return session->sess_driver->sess_unsubscribe_folder(session, mb);
272}
273
274/* message */
275
276int mailsession_append_message(mailsession * session,
277 char * message, size_t size)
278{
279 if (session->sess_driver->sess_append_message == NULL)
280 return MAIL_ERROR_NOT_IMPLEMENTED;
281
282 return session->sess_driver->sess_append_message(session, message, size);
283}
284
285int mailsession_append_message_flags(mailsession * session,
286 char * message, size_t size, struct mail_flags * flags)
287{
288 if (session->sess_driver->sess_append_message_flags == NULL)
289 return MAIL_ERROR_NOT_IMPLEMENTED;
290
291 return session->sess_driver->sess_append_message_flags(session,
292 message, size, flags);
293}
294
295int mailsession_copy_message(mailsession * session,
296 uint32_t num, char * mb)
297{
298 if (session->sess_driver->sess_copy_message == NULL)
299 return MAIL_ERROR_NOT_IMPLEMENTED;
300
301 return session->sess_driver->sess_copy_message(session, num, mb);
302}
303
304int mailsession_move_message(mailsession * session,
305 uint32_t num, char * mb)
306{
307 if (session->sess_driver->sess_move_message == NULL) {
308 int r;
309
310 if ((session->sess_driver->sess_copy_message == NULL) &&
311 (session->sess_driver->sess_remove_message == NULL))
312 return MAIL_ERROR_NOT_IMPLEMENTED;
313
314 r = mailsession_copy_message(session, num, mb);
315 if (r != MAIL_NO_ERROR)
316 return r;
317
318 r = mailsession_remove_message(session, num);
319 if (r != MAIL_NO_ERROR)
320 return r;
321
322 return MAIL_NO_ERROR;
323 }
324
325 return session->sess_driver->sess_move_message(session, num, mb);
326}
327
328int mailsession_get_envelopes_list(mailsession * session,
329 struct mailmessage_list * env_list)
330{
331 if (session->sess_driver->sess_get_envelopes_list == NULL)
332 return MAIL_ERROR_NOT_IMPLEMENTED;
333
334 return session->sess_driver->sess_get_envelopes_list(session, env_list);
335}
336
337int mailsession_get_messages_list(mailsession * session,
338 struct mailmessage_list ** result)
339{
340 if (session->sess_driver->sess_get_messages_list == NULL)
341 return MAIL_ERROR_NOT_IMPLEMENTED;
342
343 return session->sess_driver->sess_get_messages_list(session, result);
344}
345
346int mailsession_remove_message(mailsession * session, uint32_t num)
347{
348 if (session->sess_driver->sess_remove_message == NULL)
349 return MAIL_ERROR_NOT_IMPLEMENTED;
350
351 return session->sess_driver->sess_remove_message(session, num);
352}
353
354#if 0
355int mailsession_search_messages(mailsession * session, char * charset,
356 struct mail_search_key * key,
357 struct mail_search_result ** result)
358{
359 if (session->sess_driver->sess_search_messages == NULL)
360 return MAIL_ERROR_NOT_IMPLEMENTED;
361
362 return session->sess_driver->sess_search_messages(session,
363 charset, key, result);
364}
365#endif
366
367int mailsession_get_message(mailsession * session,
368 uint32_t num, mailmessage ** result)
369{
370 if (session->sess_driver->sess_get_message == NULL)
371 return MAIL_ERROR_NOT_IMPLEMENTED;
372
373 return session->sess_driver->sess_get_message(session, num, result);
374}
375
376int mailsession_get_message_by_uid(mailsession * session,
377 const char * uid, mailmessage ** result)
378{
379 if (session->sess_driver->sess_get_message_by_uid == NULL)
380 return MAIL_ERROR_NOT_IMPLEMENTED;
381
382 return session->sess_driver->sess_get_message_by_uid(session, uid, result);
383}
diff --git a/libetpan/src/driver/interface/maildriver.h b/libetpan/src/driver/interface/maildriver.h
new file mode 100644
index 0000000..16e830b
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver.h
@@ -0,0 +1,546 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_H
37
38#define MAILDRIVER_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/maildriver_types_helper.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* mailsession */
48
49/*
50 mailsession_new creates a new session, using the given driver
51
52 @return the created session is returned
53*/
54
55mailsession * mailsession_new(mailsession_driver * sess_driver);
56
57/*
58 mailsession_free release the memory used by the session
59*/
60
61void mailsession_free(mailsession * session);
62
63/*
64 mailsession_parameters is used to make calls specific to the driver
65
66 @param id is the command to send to the driver,
67 usually, commands can be found in the header of the driver
68
69 @param value is the parameter of the specific call
70
71 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
72 on error
73*/
74
75int mailsession_parameters(mailsession * session,
76 int id, void * value);
77
78/*
79 There are drivers of two kinds : stream drivers (driver that connects
80 to servers through TCP or other means of connection) and file drivers
81 (driver that are based on filesystem)
82
83 The following function can only be used by stream drivers.
84 mailsession_connect_stream connects a stream to the session
85
86 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
87 on error
88*/
89
90int mailsession_connect_stream(mailsession * session, mailstream * s);
91
92/*
93 The following function can only be used by file drivers.
94 mailsession_connect_path selects the main path of the session
95
96 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
97 on error
98*/
99
100int mailsession_connect_path(mailsession * session, char * path);
101
102/*
103 NOTE: works only on stream drivers
104
105 mailsession_starttls switches the current connection to TLS (secure layer)
106
107 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
108 on error
109*/
110
111int mailsession_starttls(mailsession * session);
112
113/*
114 mailsession_login notifies the login and the password to authenticate
115 to the session
116
117 @param userid the given string is only needed at this function call
118 (it will be duplicated if necessary)
119 @param password the given string is only needed at this function call
120 (it will be duplicated if necessary)
121
122 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
123 on error
124*/
125
126int mailsession_login(mailsession * session,
127 char * userid, char * password);
128
129/*
130 NOTE: this function doesn't often work on filsystem drivers
131
132 mailsession_logout deconnects the session and closes the stream.
133
134 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
135 on error
136*/
137
138int mailsession_logout(mailsession * session);
139
140/*
141 mailsession_noop does no operation on the session, but it can be
142 used to poll for the status of the connection.
143
144 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
145 on error
146*/
147
148int mailsession_noop(mailsession * session);
149
150/*
151 NOTE: driver's specific should be used
152
153 mailsession_build_folder_name will return an allocated string with
154 that contains the complete path of the folder to create
155
156 @param session the sesion
157 @param mb is the parent mailbox
158 @param name is the name of the folder to create
159 @param result the complete path of the folder to create will be
160 stored in (* result), this name have to be freed with free()
161
162 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
163 on error
164*/
165
166int mailsession_build_folder_name(mailsession * session, char * mb,
167 char * name, char ** result);
168
169/*
170 NOTE: driver's specific should be used
171
172 mailsession_create_folder creates the folder that corresponds to the
173 given name
174
175 @param session the session
176 @param mb is the name of the mailbox
177
178 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
179 on error
180*/
181
182int mailsession_create_folder(mailsession * session, char * mb);
183
184
185/*
186 NOTE: driver's specific should be used
187
188 mailsession_delete_folder deletes the folder that corresponds to the
189 given name
190
191 @param session the session
192 @param mb is the name of the mailbox
193
194 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
195 on error
196*/
197
198int mailsession_delete_folder(mailsession * session, char * mb);
199
200
201/*
202 mailsession_rename_folder changes the name of the folder
203
204 @param session the session
205 @param mb is the name of the mailbox whose name has to be changed
206 @param new_name is the destination name (the parent
207 of the new folder folder can be other)
208
209 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
210 on error
211*/
212
213int mailsession_rename_folder(mailsession * session,
214 char * mb, char * new_name);
215
216/*
217 mailsession_check_folder makes a checkpoint of the session
218
219 @param session the session
220
221 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
222 on error
223*/
224
225int mailsession_check_folder(mailsession * session);
226
227
228/*
229 NOTE: this function is not implemented in most drivers
230
231 mailsession_examine_folder selects a mailbox as readonly
232
233 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
234 on error
235*/
236
237int mailsession_examine_folder(mailsession * session, char * mb);
238
239
240/*
241 mailsession_select_folder selects a mailbox
242
243 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
244 on error
245*/
246
247int mailsession_select_folder(mailsession * session, char * mb);
248
249
250/*
251 mailsession_expunge_folder deletes all messages marked \Deleted
252
253 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
254 on error
255*/
256
257int mailsession_expunge_folder(mailsession * session);
258
259
260/*
261 mailsession_status_folder queries the status of the folder
262 (number of messages, number of recent messages, number of unseen messages)
263
264 @param session the session
265 @param mb mailbox to query
266 @param result_messages the number of messages is stored
267 in (* result_messages)
268 @param result_recent the number of messages is stored
269 in (* result_recent)
270 @param result_unseen the number of messages is stored
271 in (* result_unseen)
272
273 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
274 on error
275*/
276
277int mailsession_status_folder(mailsession * session, char * mb,
278 uint32_t * result_messages, uint32_t * result_recent,
279 uint32_t * result_unseen);
280
281
282/*
283 mailsession_messages_number queries the number of messages in the folder
284
285 @param session the session
286 @param mb mailbox to query
287 @param result the number of messages is stored in (* result)
288
289 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
290 on error
291*/
292
293int mailsession_messages_number(mailsession * session, char * mb,
294 uint32_t * result);
295
296/*
297 mailsession_recent_number queries the number of recent messages in the folder
298
299 @param session the session
300 @param mb mailbox to query
301 @param result the number of recent messages is stored in (* result)
302
303 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
304 on error
305*/
306
307int mailsession_recent_number(mailsession * session,
308 char * mb, uint32_t * result);
309
310/*
311 mailsession_unseen_number queries the number of unseen messages in the folder
312
313 @param session the session
314 @param mb mailbox to query
315 @param result the number of unseen messages is stored in (* result)
316
317 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
318 on error
319*/
320
321int mailsession_unseen_number(mailsession * session, char * mb,
322 uint32_t * result);
323
324/*
325 NOTE: driver's specific should be used
326
327 mailsession_list_folders returns the list of all sub-mailboxes
328 of the given mailbox
329
330 @param session the session
331 @param mb the mailbox
332 @param result list of mailboxes if stored in (* result),
333 this structure have to be freed with mail_list_free()
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error
337*/
338
339int mailsession_list_folders(mailsession * session, char * mb,
340 struct mail_list ** result);
341
342/*
343 NOTE: driver's specific should be used
344
345 mailsession_lsub_folders returns the list of subscribed
346 sub-mailboxes of the given mailbox
347
348 @param session the session
349 @param mb the mailbox
350 @param result list of mailboxes if stored in (* result),
351 this structure have to be freed with mail_list_free()
352
353 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
354 on error
355*/
356
357int mailsession_lsub_folders(mailsession * session, char * mb,
358 struct mail_list ** result);
359
360/*
361 NOTE: driver's specific should be used
362
363 mailsession_subscribe_folder subscribes to the given mailbox
364
365 @param session the session
366 @param mb the mailbox
367
368 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
369 on error
370*/
371
372int mailsession_subscribe_folder(mailsession * session, char * mb);
373
374/*
375 NOTE: driver's specific should be used
376
377 mailsession_unsubscribe_folder unsubscribes to the given mailbox
378
379 @param session the session
380 @param mb the mailbox
381
382 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
383 on error
384*/
385
386int mailsession_unsubscribe_folder(mailsession * session, char * mb);
387
388/*
389 mailsession_append_message adds a RFC 2822 message to the current
390 given mailbox
391
392 @param session the session
393 @param message is a string that contains the RFC 2822 message
394 @param size this is the size of the message
395
396 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
397 on error
398*/
399
400int mailsession_append_message(mailsession * session,
401 char * message, size_t size);
402
403int mailsession_append_message_flags(mailsession * session,
404 char * message, size_t size, struct mail_flags * flags);
405
406/*
407 NOTE: some drivers does not implement this
408
409 mailsession_copy_message copies a message whose number is given to
410 a given mailbox. The mailbox must be accessible from the same session.
411
412 @param session the session
413 @param num the message number
414 @param mb the destination mailbox
415
416 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
417 on error
418*/
419
420int mailsession_copy_message(mailsession * session,
421 uint32_t num, char * mb);
422
423/*
424 NOTE: some drivers does not implement this
425
426 mailsession_move_message copies a message whose number is given to
427 a given mailbox. The mailbox must be accessible from the same session.
428
429 @param session the session
430 @param num the message number
431 @param mb the destination mailbox
432
433 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
434 on error
435*/
436
437int mailsession_move_message(mailsession * session,
438 uint32_t num, char * mb);
439
440/*
441 mailsession_get_messages_list returns the list of message numbers
442 of the current mailbox.
443
444 @param session the session
445 @param result the list of message numbers will be stored in (* result),
446 this structure have to be freed with mailmessage_list_free()
447
448 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
449 on error
450*/
451
452int mailsession_get_messages_list(mailsession * session,
453 struct mailmessage_list ** result);
454
455/*
456 mailsession_get_envelopes_list fills the parsed fields in the
457 mailmessage structures of the mailmessage_list.
458
459 @param session the session
460 @param result this is the list of mailmessage structures
461
462 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
463 on error
464*/
465
466int mailsession_get_envelopes_list(mailsession * session,
467 struct mailmessage_list * result);
468
469/*
470 NOTE: some drivers does not implement this
471
472 mailsession_remove_message removes the given message from the mailbox.
473 The message is permanently deleted.
474
475 @param session the session
476 @param num is the message number
477
478 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
479 on error
480*/
481
482int mailsession_remove_message(mailsession * session, uint32_t num);
483
484
485/*
486 NOTE: this function is not implemented in most drivers
487
488 mailsession_search_message returns a list of message numbers that
489 corresponds to the given criteria.
490
491 @param session the session
492 @param charset is the charset to use (it can be NULL)
493 @param key is the list of criteria
494 @param result the search result is stored in (* result),
495 this structure have to be freed with mail_search_result_free()
496
497 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
498 on error
499*/
500
501#if 0
502int mailsession_search_messages(mailsession * session, char * charset,
503 struct mail_search_key * key,
504 struct mail_search_result ** result);
505#endif
506
507/*
508 mailsession_get_message returns a mailmessage structure that corresponds
509 to the given message number.
510 * WARNING * mailsession_get_message_by_uid() should be used instead.
511
512 @param session the session
513 @param num the message number
514 @param result the allocated mailmessage structure will be stored
515 in (* result), this structure have to be freed with mailmessage_free()
516
517 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
518 on error
519*/
520
521int mailsession_get_message(mailsession * session,
522 uint32_t num, mailmessage ** result);
523
524/*
525 mailsession_get_message_by_uid returns a mailmessage structure
526 that corresponds to the given message unique identifier.
527 This is currently implemented only for cached drivers.
528 * WARNING * That will deprecates the use of mailsession_get_message()
529
530 @param session the session
531 @param uid the message unique identifier
532 @param result the allocated mailmessage structure will be stored
533 in (* result), this structure have to be freed with mailmessage_free()
534
535 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
536 on error
537*/
538
539int mailsession_get_message_by_uid(mailsession * session,
540 const char * uid, mailmessage ** result);
541
542#ifdef __cplusplus
543}
544#endif
545
546#endif
diff --git a/libetpan/src/driver/interface/maildriver_errors.h b/libetpan/src/driver/interface/maildriver_errors.h
new file mode 100644
index 0000000..99ec25c
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_errors.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_ERRORS_H
37
38#define MAILDRIVER_ERRORS_H
39
40enum {
41 MAIL_NO_ERROR = 0,
42 MAIL_NO_ERROR_AUTHENTICATED,
43 MAIL_NO_ERROR_NON_AUTHENTICATED,
44 MAIL_ERROR_NOT_IMPLEMENTED,
45 MAIL_ERROR_UNKNOWN,
46 MAIL_ERROR_CONNECT,
47 MAIL_ERROR_BAD_STATE,
48 MAIL_ERROR_FILE,
49 MAIL_ERROR_STREAM,
50 MAIL_ERROR_LOGIN,
51 MAIL_ERROR_CREATE, /* 10 */
52 MAIL_ERROR_DELETE,
53 MAIL_ERROR_LOGOUT,
54 MAIL_ERROR_NOOP,
55 MAIL_ERROR_RENAME,
56 MAIL_ERROR_CHECK,
57 MAIL_ERROR_EXAMINE,
58 MAIL_ERROR_SELECT,
59 MAIL_ERROR_MEMORY,
60 MAIL_ERROR_STATUS,
61 MAIL_ERROR_SUBSCRIBE, /* 20 */
62 MAIL_ERROR_UNSUBSCRIBE,
63 MAIL_ERROR_LIST,
64 MAIL_ERROR_LSUB,
65 MAIL_ERROR_APPEND,
66 MAIL_ERROR_COPY,
67 MAIL_ERROR_FETCH,
68 MAIL_ERROR_STORE,
69 MAIL_ERROR_SEARCH,
70 MAIL_ERROR_DISKSPACE,
71 MAIL_ERROR_MSG_NOT_FOUND, /* 30 */
72 MAIL_ERROR_PARSE,
73 MAIL_ERROR_INVAL,
74 MAIL_ERROR_PART_NOT_FOUND,
75 MAIL_ERROR_REMOVE,
76 MAIL_ERROR_FOLDER_NOT_FOUND,
77 MAIL_ERROR_MOVE,
78 MAIL_ERROR_STARTTLS,
79 MAIL_ERROR_CACHE_MISS,
80 MAIL_ERROR_NO_TLS,
81 MAIL_ERROR_EXPUNGE, /* 40 */
82 /* misc errors */
83 MAIL_ERROR_MISC,
84 MAIL_ERROR_PROTOCOL,
85 MAIL_ERROR_CAPABILITY,
86 MAIL_ERROR_CLOSE,
87 MAIL_ERROR_FATAL,
88 MAIL_ERROR_READONLY,
89 MAIL_ERROR_NO_APOP,
90 MAIL_ERROR_COMMAND_NOT_SUPPORTED,
91 MAIL_ERROR_NO_PERMISSION,
92 MAIL_ERROR_PROGRAM_ERROR, /* 50 */
93 MAIL_ERROR_SUBJECT_NOT_FOUND,
94 MAIL_ERROR_CHAR_ENCODING_FAILED,
95 MAIL_ERROR_SEND,
96 MAIL_ERROR_COMMAND,
97 MAIL_ERROR_SYSTEM,
98 MAIL_ERROR_UNABLE,
99 MAIL_ERROR_FOLDER,
100};
101
102#endif
diff --git a/libetpan/src/driver/interface/maildriver_tools.c b/libetpan/src/driver/interface/maildriver_tools.c
new file mode 100644
index 0000000..4501b23
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_tools.c
@@ -0,0 +1,841 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_tools.h"
37
38#include "libetpan-config.h"
39
40#include <stdlib.h>
41#include <ctype.h>
42#include <string.h>
43#include <dirent.h>
44#include <unistd.h>
45
46#include "maildriver.h"
47#include "mailmessage.h"
48#include "mailstream.h"
49#include "mailmime.h"
50#include "mail_cache_db.h"
51
52/* ********************************************************************* */
53/* tools */
54
55
56int
57maildriver_generic_get_envelopes_list(mailsession * session,
58 struct mailmessage_list * env_list)
59{
60 int r;
61 unsigned i;
62#if 0
63 uint32_t j;
64 uint32_t last_msg;
65
66 last_msg = 0;
67#endif
68
69#if 0
70 j = 0;
71 i = 0;
72 while (i < env_list->tab->len) {
73 mailmessage * msg;
74 uint32_t index;
75
76 msg = carray_get(env_list->tab, i);
77
78 index = msg->index;
79
80 if (msg->fields == NULL) {
81 struct mailimf_fields * fields;
82
83 r = mailmessage_fetch_envelope(msg, &fields);
84 if (r != MAIL_NO_ERROR) {
85 /* do nothing */
86 }
87 else {
88 msg->fields = fields;
89
90 carray_set(env_list->tab, j, msg);
91
92 j ++;
93 last_msg = i + 1;
94 }
95 mailmessage_flush(msg);
96 }
97 else {
98 j ++;
99 last_msg = i + 1;
100 }
101
102 i ++;
103 }
104
105 for(i = last_msg ; i < env_list->tab->len ; i ++) {
106 mailmessage_free(carray_get(env_list->tab, i));
107 carray_set(env_list->tab, i, NULL);
108 }
109
110 r = carray_set_size(env_list->tab, j);
111 if (r < 0)
112 return MAIL_ERROR_MEMORY;
113#endif
114
115 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
116 mailmessage * msg;
117
118 msg = carray_get(env_list->msg_tab, i);
119
120 if (msg->msg_fields == NULL) {
121 struct mailimf_fields * fields;
122
123 r = mailmessage_fetch_envelope(msg, &fields);
124 if (r != MAIL_NO_ERROR) {
125 /* do nothing */
126 }
127 else {
128 msg->msg_fields = fields;
129 }
130 mailmessage_flush(msg);
131 }
132 }
133
134 return MAIL_NO_ERROR;
135}
136
137
138#if 0
139static int is_search_header_only(struct mail_search_key * key)
140{
141 clistiter * cur;
142 int result;
143
144 switch (key->type) {
145 case MAIL_SEARCH_KEY_ANSWERED:
146 case MAIL_SEARCH_KEY_BCC:
147 case MAIL_SEARCH_KEY_BEFORE:
148 case MAIL_SEARCH_KEY_CC:
149 case MAIL_SEARCH_KEY_DELETED:
150 case MAIL_SEARCH_KEY_FLAGGED:
151 case MAIL_SEARCH_KEY_FROM:
152 case MAIL_SEARCH_KEY_NEW:
153 case MAIL_SEARCH_KEY_OLD:
154 case MAIL_SEARCH_KEY_ON:
155 case MAIL_SEARCH_KEY_RECENT:
156 case MAIL_SEARCH_KEY_SEEN:
157 case MAIL_SEARCH_KEY_SINCE:
158 case MAIL_SEARCH_KEY_SUBJECT:
159 case MAIL_SEARCH_KEY_TO:
160 case MAIL_SEARCH_KEY_UNANSWERED:
161 case MAIL_SEARCH_KEY_UNDELETED:
162 case MAIL_SEARCH_KEY_UNFLAGGED:
163 case MAIL_SEARCH_KEY_UNSEEN:
164 case MAIL_SEARCH_KEY_HEADER:
165 case MAIL_SEARCH_KEY_LARGER:
166 case MAIL_SEARCH_KEY_NOT:
167 case MAIL_SEARCH_KEY_SMALLER:
168 case MAIL_SEARCH_KEY_ALL:
169 return TRUE;
170
171 case MAIL_SEARCH_KEY_BODY:
172 case MAIL_SEARCH_KEY_TEXT:
173 return FALSE;
174
175 case MAIL_SEARCH_KEY_OR:
176 return (is_search_header_only(key->or1) &&
177 is_search_header_only(key->or2));
178
179 case MAIL_SEARCH_KEY_MULTIPLE:
180 result = TRUE;
181 for (cur = clist_begin(key->multiple) ; cur != NULL ;
182 cur = clist_next(cur))
183 result = result && is_search_header_only(clist_content(cur));
184 return result;
185
186 default:
187 return TRUE;
188 }
189}
190
191static int match_header(struct mailimf_fields * fields,
192 char * name, char * value)
193{
194 clistiter * cur;
195
196 for(cur = clist_begin(fields->list) ; cur != NULL ;
197 cur = clist_content(cur)) {
198 struct mailimf_field * field;
199 struct mailimf_optional_field * opt_field;
200
201 field = clist_content(cur);
202 opt_field = field->optional_field;
203 if ((char) toupper((unsigned char) opt_field->name[0]) ==
204 (char) toupper((unsigned char) name[0])) {
205 if (strcasecmp(opt_field->name, name) == 0)
206 if (strstr(opt_field->value, value) != NULL)
207 return TRUE;
208 }
209 }
210 return FALSE;
211}
212
213static int comp_date(struct mailimf_fields * fields,
214 struct mailimf_date_time * ref_date)
215{
216 clistiter * cur;
217 struct mailimf_date_time * date;
218 int r;
219
220 date = NULL;
221 for(cur = clist_begin(fields->list) ; cur != NULL ;
222 cur = clist_content(cur)) {
223 struct mailimf_field * field;
224 struct mailimf_optional_field * opt_field;
225
226 field = clist_content(cur);
227 opt_field = field->optional_field;
228 if ((char) toupper((unsigned char) opt_field->name[0]) == 'D') {
229 if (strcasecmp(opt_field->name, "Date") == 0) {
230 size_t cur_token;
231
232 cur_token = 0;
233 r = mailimf_date_time_parse(opt_field->value, strlen(opt_field->value),
234 &cur_token, &date);
235 if (r == MAILIMF_NO_ERROR)
236 break;
237 else if (r == MAILIMF_ERROR_PARSE) {
238 /* do nothing */
239 }
240 else
241 break;
242 }
243 }
244 }
245
246 if (date == NULL)
247 return 0;
248
249 return mailimf_date_time_comp(date, ref_date);
250}
251
252static int match_messages(char * message,
253 size_t size,
254 struct mailimf_fields * fields,
255 int32_t flags,
256 char * charset,
257 struct mail_search_key * key)
258{
259 clistiter * cur;
260 size_t length;
261 size_t cur_token;
262 int r;
263
264 switch (key->type) {
265
266 /* flags */
267 case MAIL_SEARCH_KEY_ANSWERED:
268 return ((flags & MAIL_FLAG_ANSWERED) != 0);
269
270 case MAIL_SEARCH_KEY_FLAGGED:
271 return ((flags & MAIL_FLAG_FLAGGED) != 0);
272
273 case MAIL_SEARCH_KEY_DELETED:
274 return ((flags & MAIL_FLAG_DELETED) != 0);
275
276 case MAIL_SEARCH_KEY_RECENT:
277 return ((flags & MAIL_FLAG_NEW) != 0) &&
278 ((flags & MAIL_FLAG_SEEN) == 0);
279
280 case MAIL_SEARCH_KEY_SEEN:
281 return ((flags & MAIL_FLAG_SEEN) != 0);
282
283 case MAIL_SEARCH_KEY_NEW:
284 return ((flags & MAIL_FLAG_NEW) != 0);
285
286 case MAIL_SEARCH_KEY_OLD:
287 return ((flags & MAIL_FLAG_NEW) == 0);
288
289 case MAIL_SEARCH_KEY_UNANSWERED:
290 return ((flags & MAIL_FLAG_ANSWERED) == 0);
291
292 case MAIL_SEARCH_KEY_UNDELETED:
293 return ((flags & MAIL_FLAG_DELETED) == 0);
294
295 case MAIL_SEARCH_KEY_UNFLAGGED:
296 return ((flags & MAIL_FLAG_FLAGGED) == 0);
297
298 case MAIL_SEARCH_KEY_UNSEEN:
299 return ((flags & MAIL_FLAG_SEEN) == 0);
300
301 /* headers */
302 case MAIL_SEARCH_KEY_BCC:
303 return match_header(fields, "Bcc", key->bcc);
304
305 case MAIL_SEARCH_KEY_CC:
306 return match_header(fields, "Cc", key->cc);
307
308 case MAIL_SEARCH_KEY_FROM:
309 return match_header(fields, "From", key->from);
310
311 case MAIL_SEARCH_KEY_SUBJECT:
312 return match_header(fields, "Subject", key->subject);
313
314 case MAIL_SEARCH_KEY_TO:
315 return match_header(fields, "To", key->to);
316
317 case MAIL_SEARCH_KEY_HEADER:
318 return match_header(fields, key->header_name, key->header_value);
319
320 /* date */
321 case MAIL_SEARCH_KEY_BEFORE:
322 return (comp_date(fields, key->before) <= 0);
323
324 case MAIL_SEARCH_KEY_ON:
325 return (comp_date(fields, key->before) == 0);
326
327 case MAIL_SEARCH_KEY_SINCE:
328 return (comp_date(fields, key->before) >= 0);
329
330 /* boolean */
331 case MAIL_SEARCH_KEY_NOT:
332 return (!match_messages(message, size, fields, flags, charset, key->not));
333 case MAIL_SEARCH_KEY_OR:
334 return (match_messages(message, size, fields, flags, charset, key->or1) ||
335 match_messages(message, size, fields, flags, charset, key->or2));
336
337 case MAIL_SEARCH_KEY_MULTIPLE:
338 for(cur = clist_begin(key->multiple) ; cur != NULL ;
339 cur = clist_next(cur)) {
340 if (!match_messages(message, size, fields, flags, charset,
341 clist_content(cur)))
342 return FALSE;
343 }
344
345 return TRUE;
346
347 /* size */
348 case MAIL_SEARCH_KEY_SMALLER:
349 return (size <= key->smaller);
350
351 case MAIL_SEARCH_KEY_LARGER:
352 return (size >= key->larger);
353
354 case MAIL_SEARCH_KEY_BODY:
355 length = strlen(message);
356
357 cur_token = 0;
358 while (1) {
359 r = mailimf_ignore_field_parse(message, length, &cur_token);
360 if (r == MAILIMF_NO_ERROR) {
361 /* do nothing */
362 }
363 else
364 break;
365 }
366
367 return (strstr(message + cur_token, key->body) != NULL);
368
369 case MAIL_SEARCH_KEY_TEXT:
370 return (strstr(message, key->body) != NULL);
371
372 case MAIL_SEARCH_KEY_ALL:
373 default:
374 return TRUE;
375 }
376}
377
378int maildriver_generic_search_messages(mailsession * session, char * charset,
379 struct mail_search_key * key,
380 struct mail_search_result ** result)
381{
382 int header;
383 clist * list;
384 struct mail_search_result * search_result;
385 int r;
386 struct mailmessage_list * env_list;
387 int res;
388 unsigned int i;
389
390 header = is_search_header_only(key);
391
392 r = mailsession_get_messages_list(session, &env_list);
393 if (r != MAIL_NO_ERROR)
394 return r;
395
396 list = NULL;
397 for(i = 0 ; i < carray_count(env_list->tab) ; i ++) {
398 char * message;
399 size_t length;
400 struct mail_info * info;
401 uint32_t flags;
402 struct mailimf_fields * fields;
403 size_t cur_token;
404
405 info = carray_get(env_list->tab, i);
406
407 if (!header) {
408 r = mailsession_fetch_message(session, info->index, &message, &length);
409 if (r != MAIL_NO_ERROR) {
410 res = r;
411 goto free_list;
412 }
413
414 cur_token = 0;
415 r = mailimf_optional_fields_parse(message, length,
416 &cur_token, &fields);
417 if (r != MAILIMF_NO_ERROR) {
418 res = MAIL_ERROR_PARSE;
419 goto free_list;
420 }
421 }
422 else {
423 char * msg_header;
424 int r;
425 size_t cur_token;
426 size_t header_len;
427
428 r = mailsession_fetch_message_header(session, info->index, &msg_header,
429 &header_len);
430 if (r != MAIL_NO_ERROR) {
431 res = r;
432 goto free_list;
433 }
434
435 message = NULL;
436 cur_token = 0;
437 r = mailimf_optional_fields_parse(msg_header, header_len,
438 &cur_token, &fields);
439 if (r != MAILIMF_NO_ERROR) {
440 res = MAIL_ERROR_PARSE;
441 goto free_list;
442 }
443
444 mailsession_fetch_result_free(session, msg_header);
445 }
446
447 r = mailsession_get_message_flags(session, info->index, &flags);
448 if (r != MAIL_NO_ERROR) {
449 res = r;
450 goto free_list;
451 }
452
453 if (match_messages(message, info->size, fields, flags,
454 charset, key)) {
455 uint32_t * pnum;
456
457 pnum = malloc(sizeof(* pnum));
458 if (pnum == NULL) {
459 if (message != NULL)
460 mailsession_fetch_result_free(session, message);
461 res = MAIL_ERROR_MEMORY;
462 goto free_list;
463 }
464
465 * pnum = info->index;
466
467 r = clist_append(list, pnum);
468 if (r < 0) {
469 free(pnum);
470 if (message != NULL)
471 mailsession_fetch_result_free(session, message);
472 res = MAIL_ERROR_MEMORY;
473 goto free_list;
474 }
475 }
476
477 if (message != NULL)
478 mailsession_fetch_result_free(session, message);
479 }
480
481 search_result = mail_search_result_new(list);
482 if (search_result == NULL) {
483 res = MAIL_ERROR_MEMORY;
484 goto free_list;
485 }
486
487 * result = search_result;
488
489 return MAIL_NO_ERROR;
490
491 free_list:
492 clist_foreach(list, (clist_func) free, NULL);
493 clist_free(list);
494 mailmessage_list_free(env_list);
495 return res;
496}
497#endif
498
499#if 0
500int maildriver_generic_search_messages(mailsession * session, char * charset,
501 struct mail_search_key * key,
502 struct mail_search_result ** result)
503{
504 return MAIL_ERROR_NOT_IMPLEMENTED;
505}
506#endif
507
508int
509maildriver_env_list_to_msg_list(struct mailmessage_list * env_list,
510 clist ** result)
511{
512 clist * msg_list;
513 int r;
514 int res;
515 unsigned int i;
516
517 msg_list = clist_new();
518 if (msg_list == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
524 mailmessage * msg;
525
526 msg = carray_get(env_list->msg_tab, i);
527
528 if (msg->msg_fields == NULL) {
529 uint32_t * pindex;
530
531 pindex = malloc(sizeof(* pindex));
532 if (pindex == NULL) {
533 res = MAIL_ERROR_MEMORY;
534 goto free_msg_list;
535 }
536
537 * pindex = msg->msg_index;
538
539 r = clist_append(msg_list, pindex);
540 if (r < 0) {
541 free(pindex);
542 res = MAIL_ERROR_MEMORY;
543 goto free_msg_list;
544 }
545
546 }
547 }
548
549 * result = msg_list;
550
551 return MAIL_NO_ERROR;
552
553 free_msg_list:
554 clist_foreach(msg_list, (clist_func) free, NULL);
555 clist_free(msg_list);
556 err:
557 return res;
558}
559
560
561int
562maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list,
563 clist ** result)
564{
565 clist * msg_list;
566 int r;
567 int res;
568 unsigned int i;
569
570 msg_list = clist_new();
571 if (msg_list == NULL) {
572 res = MAIL_ERROR_MEMORY;
573 goto err;
574 }
575
576 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
577 mailmessage * msg;
578
579 msg = carray_get(env_list->msg_tab, i);
580
581 if (msg->msg_flags == NULL) {
582 uint32_t * pindex;
583
584 pindex = malloc(sizeof(* pindex));
585 if (pindex == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto free_msg_list;
588 }
589
590 * pindex = msg->msg_index;
591
592 r = clist_append(msg_list, pindex);
593 if (r < 0) {
594 free(pindex);
595 res = MAIL_ERROR_MEMORY;
596 goto free_msg_list;
597 }
598
599 }
600 }
601
602 * result = msg_list;
603
604 return MAIL_NO_ERROR;
605
606 free_msg_list:
607 clist_foreach(msg_list, (clist_func) free, NULL);
608 clist_free(msg_list);
609 err:
610 return res;
611}
612
613
614
615int maildriver_imf_error_to_mail_error(int error)
616{
617 switch (error) {
618 case MAILIMF_NO_ERROR:
619 return MAIL_NO_ERROR;
620
621 case MAILIMF_ERROR_PARSE:
622 return MAIL_ERROR_PARSE;
623
624 case MAILIMF_ERROR_MEMORY:
625 return MAIL_ERROR_MEMORY;
626
627 case MAILIMF_ERROR_INVAL:
628 return MAIL_ERROR_INVAL;
629
630 case MAILIMF_ERROR_FILE:
631 return MAIL_ERROR_FILE;
632
633 default:
634 return MAIL_ERROR_INVAL;
635 }
636}
637
638char * maildriver_quote_mailbox(char * mb)
639{
640 MMAPString * gstr;
641 char * str;
642
643 gstr = mmap_string_new("");
644 if (gstr == NULL)
645 return NULL;
646
647 while (* mb != 0) {
648 char hex[3];
649
650 if (((* mb >= 'a') && (* mb <= 'z')) ||
651 ((* mb >= 'A') && (* mb <= 'Z')) ||
652 ((* mb >= '0') && (* mb <= '9')))
653 mmap_string_append_c(gstr, * mb);
654 else {
655 if (mmap_string_append_c(gstr, '%') == NULL)
656 goto free;
657 snprintf(hex, 3, "%02x", (unsigned char) (* mb));
658 if (mmap_string_append(gstr, hex) == NULL)
659 goto free;
660 }
661 mb ++;
662 }
663
664 str = strdup(gstr->str);
665 if (str == NULL)
666 goto free;
667
668 mmap_string_free(gstr);
669
670 return str;
671
672 free:
673 mmap_string_free(gstr);
674 return NULL;
675}
676
677
678
679int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env,
680 struct mail_cache_db * cache_db_flags,
681 struct mailmessage_list * env_list)
682{
683 chash * hash_exist;
684 int res;
685 int r;
686 char keyname[PATH_MAX];
687 unsigned int i;
688
689 /* flush cache */
690
691 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
692 if (hash_exist == NULL) {
693 res = MAIL_ERROR_MEMORY;
694 goto err;
695 }
696
697 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
698 mailmessage * msg;
699 chashdatum key;
700 chashdatum value;
701
702 msg = carray_get(env_list->msg_tab, i);
703
704 value.data = NULL;
705 value.len = 0;
706
707 if (cache_db_env != NULL) {
708 snprintf(keyname, PATH_MAX, "%s-envelope", msg->msg_uid);
709
710 key.data = keyname;
711 key.len = strlen(keyname);
712 r = chash_set(hash_exist, &key, &value, NULL);
713 if (r < 0) {
714 res = MAIL_ERROR_MEMORY;
715 goto free;
716 }
717 }
718
719 if (cache_db_flags != NULL) {
720 snprintf(keyname, PATH_MAX, "%s-flags", msg->msg_uid);
721
722 key.data = keyname;
723 key.len = strlen(keyname);
724 r = chash_set(hash_exist, &key, &value, NULL);
725 if (r < 0) {
726 res = MAIL_ERROR_MEMORY;
727 goto free;
728 }
729 }
730 }
731
732 /* clean up */
733 if (cache_db_env != NULL)
734 mail_cache_db_clean_up(cache_db_env, hash_exist);
735 if (cache_db_flags != NULL)
736 mail_cache_db_clean_up(cache_db_flags, hash_exist);
737
738 chash_free(hash_exist);
739
740 return MAIL_NO_ERROR;
741
742 free:
743 chash_free(hash_exist);
744 err:
745 return res;
746}
747
748
749/*
750 maildriver_message_cache_clean_up()
751
752 remove files in cache_dir that does not correspond to a message.
753
754 get_uid_from_filename() modifies the given filename so that it
755 is a uid when returning from the function. If get_uid_from_filename()
756 clears the content of file (set to empty string), this means that
757 this file should not be deleted.
758*/
759
760int maildriver_message_cache_clean_up(char * cache_dir,
761 struct mailmessage_list * env_list,
762 void (* get_uid_from_filename)(char *))
763{
764 chash * hash_exist;
765 DIR * d;
766 char cached_filename[PATH_MAX];
767 struct dirent * ent;
768 char keyname[PATH_MAX];
769 unsigned int i;
770 int res;
771 int r;
772
773 /* remove files */
774
775 hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
776 if (hash_exist == NULL) {
777 res = MAIL_ERROR_MEMORY;
778 goto err;
779 }
780
781 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
782 mailmessage * msg;
783 chashdatum key;
784 chashdatum value;
785
786 msg = carray_get(env_list->msg_tab, i);
787
788 key.data = msg->msg_uid;
789 key.len = strlen(msg->msg_uid);
790 value.data = NULL;
791 value.len = 0;
792 r = chash_set(hash_exist, &key, &value, NULL);
793 if (r < 0) {
794 res = MAIL_ERROR_MEMORY;
795 goto free;
796 }
797 }
798
799 d = opendir(cache_dir);
800 while ((ent = readdir(d)) != NULL) {
801 chashdatum key;
802 chashdatum value;
803
804 if (strcmp(ent->d_name, ".") == 0)
805 continue;
806
807 if (strcmp(ent->d_name, "..") == 0)
808 continue;
809
810 if (strstr(ent->d_name, ".db") != NULL)
811 continue;
812
813 strncpy(keyname, ent->d_name, sizeof(keyname));
814 keyname[sizeof(keyname) - 1] = '\0';
815
816 get_uid_from_filename(keyname);
817
818 if (* keyname == '\0')
819 continue;
820
821 key.data = keyname;
822 key.len = strlen(keyname);
823
824 r = chash_get(hash_exist, &key, &value);
825 if (r < 0) {
826 snprintf(cached_filename, sizeof(cached_filename),
827 "%s/%s", cache_dir, ent->d_name);
828 unlink(cached_filename);
829 }
830 }
831 closedir(d);
832
833 chash_free(hash_exist);
834
835 return MAIL_NO_ERROR;
836
837 free:
838 chash_free(hash_exist);
839 err:
840 return res;
841}
diff --git a/libetpan/src/driver/interface/maildriver_tools.h b/libetpan/src/driver/interface/maildriver_tools.h
new file mode 100644
index 0000000..a92af42
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_tools.h
@@ -0,0 +1,81 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TOOLS_H
37
38#define MAILDRIVER_TOOLS_H
39
40#include "maildriver_types.h"
41#include "mail_cache_db_types.h"
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47int
48maildriver_generic_get_envelopes_list(mailsession * session,
49 struct mailmessage_list * env_list);
50
51#if 0
52int maildriver_generic_search_messages(mailsession * session, char * charset,
53 struct mail_search_key * key,
54 struct mail_search_result ** result);
55#endif
56
57int
58maildriver_env_list_to_msg_list(struct mailmessage_list * env_list,
59 clist ** result);
60
61int maildriver_imf_error_to_mail_error(int error);
62
63char * maildriver_quote_mailbox(char * mb);
64
65int
66maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list,
67 clist ** result);
68
69int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env,
70 struct mail_cache_db * cache_db_flags,
71 struct mailmessage_list * env_list);
72
73int maildriver_message_cache_clean_up(char * cache_dir,
74 struct mailmessage_list * env_list,
75 void (* get_uid_from_filename)(char *));
76
77#ifdef __cplusplus
78}
79#endif
80
81#endif
diff --git a/libetpan/src/driver/interface/maildriver_types.c b/libetpan/src/driver/interface/maildriver_types.c
new file mode 100644
index 0000000..43f5c4f
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types.c
@@ -0,0 +1,340 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_types.h"
37#include <time.h>
38#include <stdlib.h>
39#include "mailmessage.h"
40
41struct mailmessage_list * mailmessage_list_new(carray * msg_tab)
42{
43 struct mailmessage_list * env_list;
44
45 env_list = malloc(sizeof(* env_list));
46 if (env_list == NULL)
47 return NULL;
48
49 env_list->msg_tab = msg_tab;
50
51 return env_list;
52}
53
54void mailmessage_list_free(struct mailmessage_list * env_list)
55{
56 unsigned int i;
57
58 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
59 mailmessage * msg;
60
61 msg = carray_get(env_list->msg_tab, i);
62 if (msg != NULL)
63 mailmessage_free(msg);
64 }
65 carray_free(env_list->msg_tab);
66 free(env_list);
67}
68
69struct mail_list * mail_list_new(clist * list)
70{
71 struct mail_list * resp;
72
73 resp = malloc(sizeof(* resp));
74 if (resp == NULL)
75 return NULL;
76 resp->mb_list = list;
77
78 return resp;
79}
80
81void mail_list_free(struct mail_list * resp)
82{
83 clist_foreach(resp->mb_list, (clist_func) free, NULL);
84 clist_free(resp->mb_list);
85 free(resp);
86}
87
88static int32_t mailimf_date_time_to_int(struct mailimf_date_time * date)
89{
90 return date->dt_year * 12 * 30 * 24 * 60 * 60 +
91 date->dt_month * 30 * 24 * 60 * 60 + date->dt_day * 24 * 60 * 60 +
92 (date->dt_hour - date->dt_zone) * 60 * 60 +
93 date->dt_min * 60 + date->dt_sec;
94}
95
96int32_t mailimf_date_time_comp(struct mailimf_date_time * date1,
97 struct mailimf_date_time * date2)
98{
99 return mailimf_date_time_to_int(date1) - mailimf_date_time_to_int(date2);
100}
101
102
103
104
105
106
107
108#if 0
109struct mail_search_key *
110mail_search_key_new(int sk_type,
111 char * sk_bcc,
112 struct mailimf_date_time * sk_before,
113 char * sk_body,
114 char * sk_cc,
115 char * sk_from,
116 struct mailimf_date_time * sk_on,
117 struct mailimf_date_time * sk_since,
118 char * sk_subject,
119 char * sk_text,
120 char * sk_to,
121 char * sk_header_name,
122 char * sk_header_value,
123 size_t sk_larger,
124 struct mail_search_key * sk_not,
125 struct mail_search_key * sk_or1,
126 struct mail_search_key * sk_or2,
127 size_t sk_smaller,
128 clist * sk_multiple)
129{
130 struct mail_search_key * key;
131
132 key = malloc(sizeof(* key));
133 if (key == NULL)
134 return NULL;
135
136 key->sk_type = sk_type;
137 key->sk_bcc = sk_bcc;
138 key->sk_before = sk_before;
139 key->sk_body = sk_body;
140 key->sk_cc = sk_cc;
141 key->sk_from = sk_from;
142 key->sk_on = sk_on;
143 key->sk_since = sk_since;
144 key->sk_subject = sk_subject;
145 key->sk_text = sk_text;
146 key->sk_to = sk_to;
147 key->sk_header_name = sk_header_name;
148 key->sk_header_value = sk_header_value;
149 key->sk_larger = sk_larger;
150 key->sk_not = sk_not;
151 key->sk_or1 = sk_or1;
152 key->sk_or2 = sk_or2;
153 key->sk_smaller = sk_smaller;
154 key->sk_multiple = sk_multiple;
155
156 return key;
157}
158
159
160void mail_search_key_free(struct mail_search_key * key)
161{
162 if (key->sk_bcc)
163 free(key->sk_bcc);
164 if (key->sk_before)
165 mailimf_date_time_free(key->sk_before);
166 if (key->sk_body)
167 free(key->sk_body);
168 if (key->sk_cc)
169 free(key->sk_cc);
170 if (key->sk_from)
171 free(key->sk_from);
172 if (key->sk_on)
173 mailimf_date_time_free(key->sk_on);
174 if (key->sk_since)
175 mailimf_date_time_free(key->sk_since);
176 if (key->sk_subject)
177 free(key->sk_subject);
178 if (key->sk_text)
179 free(key->sk_text);
180 if (key->sk_to)
181 free(key->sk_to);
182 if (key->sk_header_name)
183 free(key->sk_header_name);
184 if (key->sk_header_value)
185 free(key->sk_header_value);
186 if (key->sk_not)
187 mail_search_key_free(key->sk_not);
188 if (key->sk_or1)
189 mail_search_key_free(key->sk_or1);
190 if (key->sk_or2)
191 mail_search_key_free(key->sk_or2);
192 if (key->sk_multiple) {
193 clist_foreach(key->sk_multiple, (clist_func) mail_search_key_free, NULL);
194 clist_free(key->sk_multiple);
195 }
196
197 free(key);
198}
199
200
201struct mail_search_result * mail_search_result_new(clist * list)
202{
203 struct mail_search_result * search_result;
204
205 search_result = malloc(sizeof(* search_result));
206 if (search_result == NULL)
207 return NULL;
208 search_result->list = list;
209
210 return search_result;
211}
212
213void mail_search_result_free(struct mail_search_result * search_result)
214{
215 clist_foreach(search_result->list, (clist_func) free, NULL);
216 clist_free(search_result->list);
217 free(search_result);
218}
219#endif
220
221struct error_message {
222 int code;
223 char * message;
224};
225
226static struct error_message message_tab[] = {
227{ MAIL_NO_ERROR, "no error" },
228{ MAIL_NO_ERROR_AUTHENTICATED, "no error - authenticated" },
229{ MAIL_NO_ERROR_NON_AUTHENTICATED, "no error - not authenticated" },
230{ MAIL_ERROR_NOT_IMPLEMENTED, "not implemented" },
231{ MAIL_ERROR_UNKNOWN, "unknown"},
232{ MAIL_ERROR_CONNECT, "connect"},
233{ MAIL_ERROR_BAD_STATE, "bad state"},
234{ MAIL_ERROR_FILE, "file error - file could not be accessed" },
235{ MAIL_ERROR_STREAM, "stream error - socket could not be read or written" },
236{ MAIL_ERROR_LOGIN, "login error" },
237{ MAIL_ERROR_CREATE, "create error" },
238{ MAIL_ERROR_DELETE, /* 10 */ "delete error" },
239{ MAIL_ERROR_LOGOUT, "logout error" },
240{ MAIL_ERROR_NOOP, "noop error" },
241{ MAIL_ERROR_RENAME, "rename error" },
242{ MAIL_ERROR_CHECK, "check error" },
243{ MAIL_ERROR_EXAMINE, "examine error" },
244{ MAIL_ERROR_SELECT, "select error - folder does not exist" },
245{ MAIL_ERROR_MEMORY, "not enough memory" },
246{ MAIL_ERROR_STATUS, "status error" },
247{ MAIL_ERROR_SUBSCRIBE, "subscribe error" },
248{ MAIL_ERROR_UNSUBSCRIBE, /* 20 */ "unsubscribe error" },
249{ MAIL_ERROR_LIST, "list error" },
250{ MAIL_ERROR_LSUB, "lsub error" },
251{ MAIL_ERROR_APPEND, "append error - mail could not be appended" },
252{ MAIL_ERROR_COPY, "copy error" },
253{ MAIL_ERROR_FETCH, "fetch error" },
254{ MAIL_ERROR_STORE, "store error" },
255{ MAIL_ERROR_SEARCH, "search error" },
256{ MAIL_ERROR_DISKSPACE, " error: not enough diskspace" },
257{ MAIL_ERROR_MSG_NOT_FOUND, "message not found" },
258{ MAIL_ERROR_PARSE, /* 30 */ "parse error" },
259{ MAIL_ERROR_INVAL, "invalid parameter for the function" },
260{ MAIL_ERROR_PART_NOT_FOUND, "mime part of the message is not found" },
261{ MAIL_ERROR_REMOVE, "remove error - the message did not exist" },
262{ MAIL_ERROR_FOLDER_NOT_FOUND, "folder not found" },
263{ MAIL_ERROR_MOVE, "move error" },
264{ MAIL_ERROR_STARTTLS, "starttls error" },
265{ MAIL_ERROR_CACHE_MISS, "mail cache missed" },
266{ MAIL_ERROR_NO_TLS, "no starttls" },
267{ MAIL_ERROR_EXPUNGE, "expunge error" },
268{ MAIL_ERROR_PROTOCOL, "protocol error - server did not respect the protocol" },
269{ MAIL_ERROR_CAPABILITY, "capability error" },
270{ MAIL_ERROR_CLOSE, "close error" },
271{ MAIL_ERROR_FATAL, "fatal error" },
272{ MAIL_ERROR_READONLY, "mailbox is readonly" },
273{ MAIL_ERROR_NO_APOP, "pop3 error - no apop" },
274{ MAIL_ERROR_COMMAND_NOT_SUPPORTED, "nntp error - command not supported" },
275{ MAIL_ERROR_NO_PERMISSION, "nntp error - no permission" },
276{ MAIL_ERROR_PROGRAM_ERROR, "nntp error - program error" },
277{ MAIL_ERROR_SUBJECT_NOT_FOUND, "internal threading error - subject not found" }};
278
279const char * maildriver_strerror(int err)
280{
281 int count;
282 int i;
283
284 count = sizeof(message_tab) / sizeof(struct error_message);
285
286 for(i = 0 ; i < count ; i++) {
287 if (message_tab[i].code == err) {
288 return message_tab[i].message;
289 }
290 }
291
292 return "unknown error";
293}
294
295
296struct mail_flags * mail_flags_new_empty(void)
297{
298 struct mail_flags * flags;
299
300 flags = malloc(sizeof(* flags));
301 if (flags == NULL)
302 goto err;
303
304 flags->fl_flags = MAIL_FLAG_NEW;
305 flags->fl_extension = clist_new();
306 if (flags->fl_extension == NULL)
307 goto free;
308
309 return flags;
310
311 free:
312 free(flags);
313 err:
314 return NULL;
315}
316
317struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_extension)
318{
319 struct mail_flags * flags;
320
321 flags = malloc(sizeof(* flags));
322 if (flags == NULL)
323 goto err;
324
325 flags->fl_flags = fl_flags;
326 flags->fl_extension = fl_extension;
327
328 return flags;
329
330err:
331 return NULL;
332}
333
334void mail_flags_free(struct mail_flags * flags)
335{
336 clist_foreach(flags->fl_extension, (clist_func) free, NULL);
337 clist_free(flags->fl_extension);
338 free(flags);
339}
340
diff --git a/libetpan/src/driver/interface/maildriver_types.h b/libetpan/src/driver/interface/maildriver_types.h
new file mode 100644
index 0000000..2225236
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types.h
@@ -0,0 +1,795 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_H
37
38#define MAILDRIVER_TYPES_H
39
40#include <inttypes.h>
41#include <sys/types.h>
42
43#include <libetpan/mailstream.h>
44#include <libetpan/mailimf.h>
45#include <libetpan/mailmime.h>
46#include <libetpan/carray.h>
47
48#include <libetpan/mailthread_types.h>
49#include <libetpan/maildriver_errors.h>
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55typedef struct mailsession_driver mailsession_driver;
56
57typedef struct mailsession mailsession;
58
59typedef struct mailmessage_driver mailmessage_driver;
60
61typedef struct mailmessage mailmessage;
62
63
64/*
65 mailmessage_list is a list of mailmessage
66
67 - tab is an array of mailmessage structures
68*/
69
70struct mailmessage_list {
71 carray * msg_tab; /* elements are (mailmessage *) */
72};
73
74struct mailmessage_list * mailmessage_list_new(carray * msg_tab);
75void mailmessage_list_free(struct mailmessage_list * env_list);
76
77/*
78 mail_list is a list of mailbox names
79
80 - list is a list of mailbox names
81*/
82
83struct mail_list {
84 clist * mb_list; /* elements are (char *) */
85};
86
87struct mail_list * mail_list_new(clist * mb_list);
88void mail_list_free(struct mail_list * resp);
89
90/*
91 This is a flag value.
92 Flags can be combined with OR operation
93*/
94
95enum {
96 MAIL_FLAG_NEW = 1 << 0,
97 MAIL_FLAG_SEEN = 1 << 1,
98 MAIL_FLAG_FLAGGED = 1 << 2,
99 MAIL_FLAG_DELETED = 1 << 3,
100 MAIL_FLAG_ANSWERED = 1 << 4,
101 MAIL_FLAG_FORWARDED = 1 << 5,
102 MAIL_FLAG_CANCELLED = 1 << 6,
103};
104
105/*
106 mail_flags is the value of a flag related to a message.
107
108 - flags is the standard flags value
109
110 - extension is a list of unknown flags for libEtPan!
111*/
112
113struct mail_flags {
114 uint32_t fl_flags;
115 clist * fl_extension; /* elements are (char *) */
116};
117
118struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext);
119void mail_flags_free(struct mail_flags * flags);
120
121/*
122 This function creates a flag for a new message
123*/
124
125struct mail_flags * mail_flags_new_empty(void);
126
127
128/*
129 mailimf_date_time_comp compares two dates
130
131
132*/
133
134int32_t mailimf_date_time_comp(struct mailimf_date_time * date1,
135 struct mailimf_date_time * date2);
136
137/*
138 this is type type of the search criteria
139*/
140
141enum {
142 MAIL_SEARCH_KEY_ALL, /* all messages correspond */
143 MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */
144 MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains
145 a given string */
146 MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier
147 than the specified date */
148 MAIL_SEARCH_KEY_BODY, /* message that contains the given string
149 (in header and text parts) */
150 MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the
151 given string */
152 MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */
153 MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */
154 MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the
155 given string */
156 MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not
157 the \Seen flag */
158 MAIL_SEARCH_KEY_OLD, /* messages that do not have the
159 \Recent flag set */
160 MAIL_SEARCH_KEY_ON, /* messages whose internal date is the
161 specified date */
162 MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */
163 MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */
164 MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later
165 than specified date */
166 MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the
167 given string */
168 MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the
169 given string */
170 MAIL_SEARCH_KEY_TO, /* messages whose To field contains the
171 given string */
172 MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */
173 MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */
174 MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */
175 MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */
176 MAIL_SEARCH_KEY_HEADER, /* messages whose given field
177 contains the given string */
178 MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then
179 the given size */
180 MAIL_SEARCH_KEY_NOT, /* not operation of the condition */
181 MAIL_SEARCH_KEY_OR, /* or operation between two conditions */
182 MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than
183 the given size */
184 MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the
185 conditions is AND */
186};
187
188/*
189 mail_search_key is the condition on the messages to return
190
191 - type is the type of the condition
192
193 - bcc is the text to search in the Bcc field when type is
194 MAIL_SEARCH_KEY_BCC, should be allocated with malloc()
195
196 - before is a date when type is MAIL_SEARCH_KEY_BEFORE
197
198 - body is the text to search in the message when type is
199 MAIL_SEARCH_KEY_BODY, should be allocated with malloc()
200
201 - cc is the text to search in the Cc field when type is
202 MAIL_SEARCH_KEY_CC, should be allocated with malloc()
203
204 - from is the text to search in the From field when type is
205 MAIL_SEARCH_KEY_FROM, should be allocated with malloc()
206
207 - on is a date when type is MAIL_SEARCH_KEY_ON
208
209 - since is a date when type is MAIL_SEARCH_KEY_SINCE
210
211 - subject is the text to search in the Subject field when type is
212 MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc()
213
214 - text is the text to search in the text part of the message when
215 type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc()
216
217 - to is the text to search in the To field when type is
218 MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc()
219
220 - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER,
221 should be allocated with malloc()
222
223 - header_value is the text to search in the given header when type is
224 MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc()
225
226 - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER
227
228 - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT
229
230 - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR
231
232 - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR
233
234 - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE
235
236 - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON
237
238 - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE
239
240 - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER
241
242 - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE
243*/
244
245#if 0
246struct mail_search_key {
247 int sk_type;
248 union {
249 char * sk_bcc;
250 struct mailimf_date_time * sk_before;
251 char * sk_body;
252 char * sk_cc;
253 char * sk_from;
254 struct mailimf_date_time * sk_on;
255 struct mailimf_date_time * sk_since;
256 char * sk_subject;
257 char * sk_text;
258 char * sk_to;
259 char * sk_header_name;
260 char * sk_header_value;
261 size_t sk_larger;
262 struct mail_search_key * sk_not;
263 struct mail_search_key * sk_or1;
264 struct mail_search_key * sk_or2;
265 size_t sk_smaller;
266 clist * sk_multiple; /* list of (struct mailimap_search_key *) */
267 } sk_data;
268};
269
270
271struct mail_search_key *
272mail_search_key_new(int sk_type,
273 char * sk_bcc, struct mailimf_date_time * sk_before,
274 char * sk_body, char * sk_cc, char * sk_from,
275 struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since,
276 char * sk_subject, char * sk_text, char * sk_to,
277 char * sk_header_name, char * sk_header_value, size_t sk_larger,
278 struct mail_search_key * sk_not, struct mail_search_key * sk_or1,
279 struct mail_search_key * sk_or2, size_t sk_smaller,
280 clist * sk_multiple);
281
282void mail_search_key_free(struct mail_search_key * key);
283#endif
284
285/*
286 mail_search_result is a list of message numbers that is returned
287 by the mailsession_search_messages function()
288*/
289
290#if 0
291struct mail_search_result {
292 clist * sr_list; /* list of (uint32_t *) */
293};
294
295struct mail_search_result * mail_search_result_new(clist * sr_list);
296
297void mail_search_result_free(struct mail_search_result * search_result);
298#endif
299
300
301/*
302 There is three kinds of identities :
303 - storage
304 - folders
305 - session
306
307 A storage (struct mailstorage) represents whether a server or
308 a main path,
309
310 A storage can be an IMAP server, the root path of a MH or a mbox file.
311
312 Folders (struct mailfolder) are the mailboxes we can
313 choose in the server or as sub-folder of the main path.
314
315 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
316 folder of the MH storage, for mbox, there is only one folder, the
317 mbox file content;
318
319 A mail session (struct mailsession) is whether a connection to a server
320 or a path that is open. It is the abstraction lower folders and storage.
321 It allow us to send commands.
322
323 We have a session driver for mail session for each kind of storage.
324
325 From a session, we can get a message (struct mailmessage) to read.
326 We have a message driver for each kind of storage.
327*/
328
329/*
330 maildriver is the driver structure for mail sessions
331
332 - name is the name of the driver
333
334 - initialize() is the function that will initializes a data structure
335 specific to the driver, it returns a value that will be stored
336 in the field data of the session.
337 The field data of the session is the state of the session,
338 the internal data structure used by the driver.
339 It is called when creating the mailsession structure with
340 mailsession_new().
341
342 - uninitialize() frees the structure created with initialize()
343
344 - parameters() implements functions specific to the given mail access
345
346 - connect_stream() connects a stream to the session
347
348 - connect_path() notify a main path to the session
349
350 - starttls() changes the current stream to a TLS stream
351
352 - login() notifies the user and the password to authenticate to the
353 session
354
355 - logout() exits the session and closes the stream
356
357 - noop() does no operation on the session, but it can be
358 used to poll for the status of the connection.
359
360 - build_folder_name() will return an allocated string with
361 that contains the complete path of the folder to create
362
363 - create_folder() creates the folder that corresponds to the
364 given name
365
366 - delete_folder() deletes the folder that corresponds to the
367 given name
368
369 - rename_folder() change the name of the folder
370
371 - check_folder() makes a checkpoint of the session
372
373 - examine_folder() selects a mailbox as readonly
374
375 - select_folder() selects a mailbox
376
377 - expunge_folder() deletes all messages marked \Deleted
378
379 - status_folder() queries the status of the folder
380 (number of messages, number of recent messages, number of
381 unseen messages)
382
383 - messages_number() queries the number of messages in the folder
384
385 - recent_number() queries the number of recent messages in the folder
386
387 - unseen_number() queries the number of unseen messages in the folder
388
389 - list_folders() returns the list of all sub-mailboxes
390 of the given mailbox
391
392 - lsub_folders() returns the list of subscribed
393 sub-mailboxes of the given mailbox
394
395 - subscribe_folder() subscribes to the given mailbox
396
397 - unsubscribe_folder() unsubscribes to the given mailbox
398
399 - append_message() adds a RFC 2822 message to the current
400 given mailbox
401
402 - copy_message() copies a message whose number is given to
403 a given mailbox. The mailbox must be accessible from
404 the same session.
405
406 - move_message() copies a message whose number is given to
407 a given mailbox. The mailbox must be accessible from the
408 same session.
409
410 - get_messages_list() returns the list of message numbers
411 of the current mailbox.
412
413 - get_envelopes_list() fills the parsed fields in the
414 mailmessage structures of the mailmessage_list.
415
416 - remove_message() removes the given message from the mailbox.
417 The message is permanently deleted.
418
419 - search_message() returns a list of message numbers that
420 corresponds to the given criteria.
421
422 - get_message returns a mailmessage structure that corresponds
423 to the given message number.
424
425 - get_message_by_uid returns a mailmessage structure that corresponds
426 to the given message unique identifier.
427
428 * mandatory functions are the following :
429
430 - connect_stream() of connect_path()
431 - logout()
432 - get_messages_list()
433 - get_envelopes_list()
434
435 * we advise you to implement these functions :
436
437 - select_folder() (in case a session can access several folders)
438 - noop() (to check if the server is responding)
439 - check_folder() (to make a checkpoint of the session)
440 - status_folder(), messages_number(), recent_number(), unseen_number()
441 (to get stat of the folder)
442 - append_message() (but can't be done in the case of POP3 at least)
443 - login() in a case of an authenticated driver.
444 - starttls() in a case of a stream driver, if the procotol supports
445 STARTTLS.
446 - get_message_by_uid() so that the application can remember the message
447 by UID and build its own list of messages.
448
449 * drivers' specific :
450
451 Everything that is specific to the driver will be implemented in this
452 function :
453
454 - parameters()
455*/
456
457struct mailsession_driver {
458 char * sess_name;
459
460 int (* sess_initialize)(mailsession * session);
461 void (* sess_uninitialize)(mailsession * session);
462
463 int (* sess_parameters)(mailsession * session,
464 int id, void * value);
465
466 int (* sess_connect_stream)(mailsession * session, mailstream * s);
467 int (* sess_connect_path)(mailsession * session, char * path);
468
469 int (* sess_starttls)(mailsession * session);
470
471 int (* sess_login)(mailsession * session, char * userid, char * password);
472 int (* sess_logout)(mailsession * session);
473 int (* sess_noop)(mailsession * session);
474
475 /* folders operations */
476
477 int (* sess_build_folder_name)(mailsession * session, char * mb,
478 char * name, char ** result);
479
480 int (* sess_create_folder)(mailsession * session, char * mb);
481 int (* sess_delete_folder)(mailsession * session, char * mb);
482 int (* sess_rename_folder)(mailsession * session, char * mb,
483 char * new_name);
484 int (* sess_check_folder)(mailsession * session);
485 int (* sess_examine_folder)(mailsession * session, char * mb);
486 int (* sess_select_folder)(mailsession * session, char * mb);
487 int (* sess_expunge_folder)(mailsession * session);
488 int (* sess_status_folder)(mailsession * session, char * mb,
489 uint32_t * result_num, uint32_t * result_recent,
490 uint32_t * result_unseen);
491 int (* sess_messages_number)(mailsession * session, char * mb,
492 uint32_t * result);
493 int (* sess_recent_number)(mailsession * session, char * mb,
494 uint32_t * result);
495 int (* sess_unseen_number)(mailsession * session, char * mb,
496 uint32_t * result);
497
498 int (* sess_list_folders)(mailsession * session, char * mb,
499 struct mail_list ** result);
500 int (* sess_lsub_folders)(mailsession * session, char * mb,
501 struct mail_list ** result);
502
503 int (* sess_subscribe_folder)(mailsession * session, char * mb);
504 int (* sess_unsubscribe_folder)(mailsession * session, char * mb);
505
506 /* messages operations */
507
508 int (* sess_append_message)(mailsession * session,
509 char * message, size_t size);
510 int (* sess_append_message_flags)(mailsession * session,
511 char * message, size_t size, struct mail_flags * flags);
512 int (* sess_copy_message)(mailsession * session,
513 uint32_t num, char * mb);
514 int (* sess_move_message)(mailsession * session,
515 uint32_t num, char * mb);
516
517 int (* sess_get_message)(mailsession * session,
518 uint32_t num, mailmessage ** result);
519
520 int (* sess_get_message_by_uid)(mailsession * session,
521 const char * uid, mailmessage ** result);
522
523 int (* sess_get_messages_list)(mailsession * session,
524 struct mailmessage_list ** result);
525 int (* sess_get_envelopes_list)(mailsession * session,
526 struct mailmessage_list * env_list);
527 int (* sess_remove_message)(mailsession * session, uint32_t num);
528#if 0
529 int (* sess_search_messages)(mailsession * session, char * charset,
530 struct mail_search_key * key,
531 struct mail_search_result ** result);
532#endif
533};
534
535
536/*
537 session is the data structure for a mail session.
538
539 - data is the internal data structure used by the driver
540 It is called when initializing the mailsession structure.
541
542 - driver is the driver used for the session
543*/
544
545struct mailsession {
546 void * sess_data;
547 mailsession_driver * sess_driver;
548};
549
550
551
552
553/*
554 mailmessage_driver is the driver structure to get information from messages.
555
556 - name is the name of the driver
557
558 - initialize() is the function that will initializes a data structure
559 specific to the driver, it returns a value that will be stored
560 in the field data of the mailsession.
561 The field data of the session is the state of the session,
562 the internal data structure used by the driver.
563 It is called when initializing the mailmessage structure with
564 mailmessage_init().
565
566 - uninitialize() frees the structure created with initialize().
567 It will be called by mailmessage_free().
568
569 - flush() will free from memory all temporary structures of the message
570 (for example, the MIME structure of the message).
571
572 - fetch_result_free() will free all strings resulted by fetch() or
573 any fetch_xxx() functions that returns a string.
574
575 - fetch() returns the content of the message (headers and text).
576
577 - fetch_header() returns the content of the headers.
578
579 - fetch_body() returns the message text (message content without headers)
580
581 - fetch_size() returns the size of the message content.
582
583 - get_bodystructure() returns the MIME structure of the message.
584
585 - fetch_section() returns the content of a given MIME part
586
587 - fetch_section_header() returns the header of the message
588 contained by the given MIME part.
589
590 - fetch_section_mime() returns the MIME headers of the
591 given MIME part.
592
593 - fetch_section_body() returns the text (if this is a message, this is the
594 message content without headers) of the given MIME part.
595
596 - fetch_envelope() returns a mailimf_fields structure, with a list of
597 fields chosen by the driver.
598
599 - get_flags() returns a the flags related to the message.
600 When you want to get flags of a message, you have to make sure to
601 call get_flags() at least once before using directly message->flags.
602*/
603
604#define LIBETPAN_MAIL_MESSAGE_CHECK
605
606struct mailmessage_driver {
607 char * msg_name;
608
609 int (* msg_initialize)(mailmessage * msg_info);
610
611 void (* msg_uninitialize)(mailmessage * msg_info);
612
613 void (* msg_flush)(mailmessage * msg_info);
614
615 void (* msg_check)(mailmessage * msg_info);
616
617 void (* msg_fetch_result_free)(mailmessage * msg_info,
618 char * msg);
619
620 int (* msg_fetch)(mailmessage * msg_info,
621 char ** result,
622 size_t * result_len);
623
624 int (* msg_fetch_header)(mailmessage * msg_info,
625 char ** result,
626 size_t * result_len);
627
628 int (* msg_fetch_body)(mailmessage * msg_info,
629 char ** result, size_t * result_len);
630
631 int (* msg_fetch_size)(mailmessage * msg_info,
632 size_t * result);
633
634 int (* msg_get_bodystructure)(mailmessage * msg_info,
635 struct mailmime ** result);
636
637 int (* msg_fetch_section)(mailmessage * msg_info,
638 struct mailmime * mime,
639 char ** result, size_t * result_len);
640
641 int (* msg_fetch_section_header)(mailmessage * msg_info,
642 struct mailmime * mime,
643 char ** result,
644 size_t * result_len);
645
646 int (* msg_fetch_section_mime)(mailmessage * msg_info,
647 struct mailmime * mime,
648 char ** result,
649 size_t * result_len);
650
651 int (* msg_fetch_section_body)(mailmessage * msg_info,
652 struct mailmime * mime,
653 char ** result,
654 size_t * result_len);
655
656 int (* msg_fetch_envelope)(mailmessage * msg_info,
657 struct mailimf_fields ** result);
658
659 int (* msg_get_flags)(mailmessage * msg_info,
660 struct mail_flags ** result);
661};
662
663
664/*
665 mailmessage is a data structure to get information from messages
666
667 - session is the session linked to the given message, it can be NULL
668
669 - driver is the message driver
670
671 - index is the message number
672
673 - uid, when it is not NULL, it means that the folder
674 the folder has persistant message numbers, the string is
675 the unique message number in the folder.
676 uid should be implemented if possible.
677 for drivers where we cannot generate real uid,
678 a suggestion is "AAAA-IIII" where AAAA is some
679 random session number and IIII the content of index field.
680
681 - size, when it is not 0, is the size of the message content.
682
683 - fields, when it is not NULL, are the header fields of the message.
684
685 - flags, when it is not NULL, are the flags related to the message.
686
687 - single_fields, when resolved != 0, is filled with the data of fields.
688
689 - mime, when it is not NULL
690
691 - cached is != 0 when the header fields were read from the cache.
692
693 - data is data specific to the driver, this is internal data structure,
694 some state of the message.
695*/
696
697struct mailmessage {
698 mailsession * msg_session;
699 mailmessage_driver * msg_driver;
700 uint32_t msg_index;
701 char * msg_uid;
702
703 size_t msg_size;
704 struct mailimf_fields * msg_fields;
705 struct mail_flags * msg_flags;
706
707 int msg_resolved;
708 struct mailimf_single_fields msg_single_fields;
709 struct mailmime * msg_mime;
710
711 /* internal data */
712
713 int msg_cached;
714 void * msg_data;
715
716 /*
717 msg_folder field :
718 used to reference the mailfolder, this is a workaround due
719 to the problem with initial conception, where folder notion
720 did not exist.
721 */
722 void * msg_folder;
723 /* user data */
724 void * msg_user_data;
725};
726
727
728/*
729 mailmessage_tree is a node in the messages tree (thread)
730
731 - parent is the parent of the message, it is NULL if the message
732 is the root of the message tree.
733
734 - date is the date of the message in number of second elapsed
735 since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
736
737 - msg is the message structure that is stored referenced by the node.
738 is msg is NULL, this is a dummy node.
739
740 - children is an array that contains all the children of the node.
741 children are mailmessage_tree structures.
742
743 - is_reply is != 0 when the message is a reply or a forward
744
745 - base_subject is the extracted subject of the message.
746
747 - index is the message number.
748*/
749
750struct mailmessage_tree {
751 struct mailmessage_tree * node_parent;
752 char * node_msgid;
753 time_t node_date;
754 mailmessage * node_msg;
755 carray * node_children; /* array of (struct mailmessage_tree *) */
756
757 /* private, used for threading */
758 int node_is_reply;
759 char * node_base_subject;
760};
761
762
763struct mailmessage_tree *
764mailmessage_tree_new(char * node_msgid, time_t node_date,
765 mailmessage * node_msg);
766
767void mailmessage_tree_free(struct mailmessage_tree * tree);
768
769/*
770 mailmessage_tree_free_recursive
771
772 if you want to release memory of the given tree and all the sub-trees,
773 you can use this function.
774*/
775
776void mailmessage_tree_free_recursive(struct mailmessage_tree * tree);
777
778
779struct generic_message_t {
780 int (* msg_prefetch)(mailmessage * msg_info);
781 void (* msg_prefetch_free)(struct generic_message_t * msg);
782 int msg_fetched;
783 char * msg_message;
784 size_t msg_length;
785 void * msg_data;
786};
787
788
789const char * maildriver_strerror(int err);
790
791#ifdef __cplusplus
792}
793#endif
794
795#endif
diff --git a/libetpan/src/driver/interface/maildriver_types_helper.c b/libetpan/src/driver/interface/maildriver_types_helper.c
new file mode 100644
index 0000000..6e3abf4
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types_helper.c
@@ -0,0 +1,104 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 200 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildriver_types_helper.h"
37
38#include "mail.h"
39
40#include "clist.h"
41#include <string.h>
42#include <stdlib.h>
43
44int mail_flags_add_extension(struct mail_flags * flags,
45 char * ext_flag)
46{
47 char * str;
48 int r;
49
50 if (mail_flags_has_extension(flags, ext_flag))
51 return MAIL_NO_ERROR;
52
53 str = strdup(ext_flag);
54 if (str == NULL)
55 return MAIL_ERROR_MEMORY;
56
57 r = clist_append(flags->fl_extension, str);
58 if (r < 0) {
59 free(str);
60 return MAIL_ERROR_MEMORY;
61 }
62
63 return MAIL_NO_ERROR;
64}
65
66int mail_flags_remove_extension(struct mail_flags * flags,
67 char * ext_flag)
68{
69 clistiter * cur;
70
71 cur = clist_begin(flags->fl_extension);
72 while (cur != NULL) {
73 char * flag_name;
74
75 flag_name = clist_content(cur);
76
77 if (strcasecmp(flag_name, ext_flag) == 0) {
78 free(flag_name);
79 cur = clist_delete(flags->fl_extension, cur);
80 }
81 else
82 cur = clist_next(cur);
83 }
84
85 return MAIL_NO_ERROR;
86}
87
88int mail_flags_has_extension(struct mail_flags * flags,
89 char * ext_flag)
90{
91 clistiter * cur;
92
93 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
94 cur = clist_next(cur)) {
95 char * flag_name;
96
97 flag_name = clist_content(cur);
98
99 if (strcasecmp(flag_name, ext_flag) == 0)
100 return TRUE;
101 }
102
103 return FALSE;
104}
diff --git a/libetpan/src/driver/interface/maildriver_types_helper.h b/libetpan/src/driver/interface/maildriver_types_helper.h
new file mode 100644
index 0000000..50ccc70
--- a/dev/null
+++ b/libetpan/src/driver/interface/maildriver_types_helper.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDRIVER_TYPES_HELPER_H
37
38#define MAILDRIVER_TYPES_HELPER_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_flags_add_extension adds the given flag if it does not exists in
48 the flags.
49
50 @param flags this is the flag to change
51
52 @param ext_flag this is the name of an extension flag
53 the given flag name is duplicated and is no more needed after
54 the function call.
55
56 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
57 on error
58*/
59
60int mail_flags_add_extension(struct mail_flags * flags,
61 char * ext_flag);
62
63/*
64 mail_flags_remove_extension removes the given flag if it does not exists in
65 the flags.
66
67 @param flags this is the flag to change
68
69 @param ext_flag this is the name of an extension flag
70 the given flag name is no more needed after the function call.
71
72 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
73 on error
74*/
75
76int mail_flags_remove_extension(struct mail_flags * flags,
77 char * ext_flag);
78
79/*
80 mail_flags_has_extension returns 1 if the flags is in the given flags,
81 0 is returned otherwise.
82
83 @param flags this is the flag to change
84
85 @param ext_flag this is the name of an extension flag
86 the given flag name is no more needed after the function call.
87
88 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
89 on error
90*/
91
92int mail_flags_has_extension(struct mail_flags * flags,
93 char * ext_flag);
94
95#ifdef __cplusplus
96}
97#endif
98
99#endif
diff --git a/libetpan/src/driver/interface/mailfolder.c b/libetpan/src/driver/interface/mailfolder.c
new file mode 100644
index 0000000..eb69d7f
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailfolder.c
@@ -0,0 +1,138 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailfolder.h"
37
38#include "maildriver.h"
39
40int mailfolder_noop(struct mailfolder * folder)
41{
42 return mailsession_noop(folder->fld_session);
43}
44
45int mailfolder_check(struct mailfolder * folder)
46{
47 return mailsession_check_folder(folder->fld_session);
48}
49
50int mailfolder_expunge(struct mailfolder * folder)
51{
52 return mailsession_expunge_folder(folder->fld_session);
53}
54
55int mailfolder_status(struct mailfolder * folder,
56 uint32_t * result_messages, uint32_t * result_recent,
57 uint32_t * result_unseen)
58{
59 return mailsession_status_folder(folder->fld_session,
60 folder->fld_pathname, result_messages,
61 result_recent, result_unseen);
62}
63
64int mailfolder_append_message(struct mailfolder * folder,
65 char * message, size_t size)
66{
67 return mailsession_append_message(folder->fld_session, message, size);
68}
69
70int mailfolder_append_message_flags(struct mailfolder * folder,
71 char * message, size_t size, struct mail_flags * flags)
72{
73 return mailsession_append_message_flags(folder->fld_session, message,
74 size, flags);
75}
76
77int mailfolder_get_messages_list(struct mailfolder * folder,
78 struct mailmessage_list ** result)
79{
80 int r;
81 struct mailmessage_list * msg_list;
82 unsigned int i;
83
84 r = mailsession_get_messages_list(folder->fld_session, &msg_list);
85 if (r != MAIL_NO_ERROR)
86 return r;
87
88 for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) {
89 mailmessage * msg;
90
91 msg = carray_get(msg_list->msg_tab, i);
92 msg->msg_folder = folder;
93 }
94
95 * result = msg_list;
96
97 return MAIL_NO_ERROR;
98}
99
100int mailfolder_get_envelopes_list(struct mailfolder * folder,
101 struct mailmessage_list * result)
102{
103 return mailsession_get_envelopes_list(folder->fld_session, result);
104}
105
106int mailfolder_get_message(struct mailfolder * folder,
107 uint32_t num, mailmessage ** result)
108{
109 mailmessage * msg;
110 int r;
111
112 r = mailsession_get_message(folder->fld_session, num, &msg);
113 if (r != MAIL_NO_ERROR)
114 return r;
115
116 msg->msg_folder = folder;
117
118 * result = msg;
119
120 return MAIL_NO_ERROR;
121}
122
123int mailfolder_get_message_by_uid(struct mailfolder * folder,
124 const char * uid, mailmessage ** result)
125{
126 mailmessage * msg;
127 int r;
128
129 r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg);
130 if (r != MAIL_NO_ERROR)
131 return r;
132
133 msg->msg_folder = folder;
134
135 * result = msg;
136
137 return MAIL_NO_ERROR;
138}
diff --git a/libetpan/src/driver/interface/mailfolder.h b/libetpan/src/driver/interface/mailfolder.h
new file mode 100644
index 0000000..55ea3be
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailfolder.h
@@ -0,0 +1,70 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILFOLDER_H
37
38#define MAILFOLDER_H
39
40#include "mailstorage_types.h"
41
42int mailfolder_noop(struct mailfolder * folder);
43
44int mailfolder_check(struct mailfolder * folder);
45
46int mailfolder_expunge(struct mailfolder * folder);
47
48int mailfolder_status(struct mailfolder * folder,
49 uint32_t * result_messages, uint32_t * result_recent,
50 uint32_t * result_unseen);
51
52int mailfolder_append_message(struct mailfolder * folder,
53 char * message, size_t size);
54
55int mailfolder_append_message_flags(struct mailfolder * folder,
56 char * message, size_t size, struct mail_flags * flags);
57
58int mailfolder_get_messages_list(struct mailfolder * folder,
59 struct mailmessage_list ** result);
60
61int mailfolder_get_envelopes_list(struct mailfolder * folder,
62 struct mailmessage_list * result);
63
64int mailfolder_get_message(struct mailfolder * folder,
65 uint32_t num, mailmessage ** result);
66
67int mailfolder_get_message_by_uid(struct mailfolder * folder,
68 const char * uid, mailmessage ** result);
69
70#endif
diff --git a/libetpan/src/driver/interface/mailmessage.c b/libetpan/src/driver/interface/mailmessage.c
new file mode 100644
index 0000000..b4921e5
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage.c
@@ -0,0 +1,240 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage.h"
37
38#include "mail.h"
39
40#include <string.h>
41
42int mailmessage_init(mailmessage * msg_info,
43 mailsession * msg_session,
44 mailmessage_driver * msg_driver,
45 uint32_t msg_index, size_t msg_size)
46{
47 int r;
48 int res;
49
50 msg_info->msg_driver = msg_driver;
51 msg_info->msg_session = msg_session;
52 msg_info->msg_index = msg_index;
53 msg_info->msg_uid = NULL;
54
55 msg_info->msg_cached = FALSE;
56 msg_info->msg_size = msg_size;
57 msg_info->msg_fields = NULL;
58 memset(&msg_info->msg_single_fields, 0,
59 sizeof(struct mailimf_single_fields));
60 msg_info->msg_resolved = FALSE;
61 msg_info->msg_flags = NULL;
62
63 msg_info->msg_mime = NULL;
64 msg_info->msg_data = NULL;
65 msg_info->msg_folder = NULL;
66 msg_info->msg_user_data = NULL;
67
68 if (msg_driver->msg_initialize != NULL) {
69 r = msg_driver->msg_initialize(msg_info);
70 if (r != MAIL_NO_ERROR) {
71 res = r;
72 goto err;
73 }
74 }
75
76 return MAIL_NO_ERROR;
77
78 err:
79 msg_info->msg_driver = NULL;
80 msg_info->msg_session = NULL;
81 return res;
82}
83
84int mailmessage_flush(mailmessage * msg_info)
85{
86 if (msg_info->msg_driver->msg_flush == NULL)
87 return MAIL_ERROR_NOT_IMPLEMENTED;
88
89 msg_info->msg_driver->msg_flush(msg_info);
90
91 return MAIL_NO_ERROR;
92}
93
94int mailmessage_check(mailmessage * msg_info)
95{
96 if (msg_info->msg_driver->msg_check == NULL)
97 return MAIL_ERROR_NOT_IMPLEMENTED;
98
99 msg_info->msg_driver->msg_check(msg_info);
100
101 return MAIL_NO_ERROR;
102}
103
104int mailmessage_fetch_result_free(mailmessage * msg_info,
105 char * msg)
106{
107 if (msg_info->msg_driver->msg_fetch_result_free == NULL)
108 return MAIL_ERROR_NOT_IMPLEMENTED;
109
110 msg_info->msg_driver->msg_fetch_result_free(msg_info, msg);
111
112 return MAIL_NO_ERROR;
113}
114
115int mailmessage_fetch(mailmessage * msg_info,
116 char ** result,
117 size_t * result_len)
118{
119 if (msg_info->msg_driver->msg_fetch == NULL)
120 return MAIL_ERROR_NOT_IMPLEMENTED;
121
122 return msg_info->msg_driver->msg_fetch(msg_info, result, result_len);
123}
124
125int mailmessage_fetch_header(mailmessage * msg_info,
126 char ** result,
127 size_t * result_len)
128{
129 if (msg_info->msg_driver->msg_fetch_header == NULL)
130 return MAIL_ERROR_NOT_IMPLEMENTED;
131
132 return msg_info->msg_driver->msg_fetch_header(msg_info, result, result_len);
133}
134
135int mailmessage_fetch_body(mailmessage * msg_info,
136 char ** result, size_t * result_len)
137{
138 if (msg_info->msg_driver->msg_fetch_body == NULL)
139 return MAIL_ERROR_NOT_IMPLEMENTED;
140
141 return msg_info->msg_driver->msg_fetch_body(msg_info, result, result_len);
142}
143
144int mailmessage_fetch_size(mailmessage * msg_info,
145 size_t * result)
146{
147 if (msg_info->msg_driver->msg_fetch_size == NULL)
148 return MAIL_ERROR_NOT_IMPLEMENTED;
149
150 return msg_info->msg_driver->msg_fetch_size(msg_info, result);
151}
152
153int mailmessage_get_bodystructure(mailmessage * msg_info,
154 struct mailmime ** result)
155{
156 if (msg_info->msg_driver->msg_get_bodystructure == NULL)
157 return MAIL_ERROR_NOT_IMPLEMENTED;
158
159 return msg_info->msg_driver->msg_get_bodystructure(msg_info, result);
160}
161
162int mailmessage_fetch_section(mailmessage * msg_info,
163 struct mailmime * mime,
164 char ** result, size_t * result_len)
165{
166 if (msg_info->msg_driver->msg_fetch_section == NULL)
167 return MAIL_ERROR_NOT_IMPLEMENTED;
168
169 return msg_info->msg_driver->msg_fetch_section(msg_info, mime, result, result_len);
170}
171
172int mailmessage_fetch_section_header(mailmessage * msg_info,
173 struct mailmime * mime,
174 char ** result,
175 size_t * result_len)
176{
177 if (msg_info->msg_driver->msg_fetch_section_header == NULL)
178 return MAIL_ERROR_NOT_IMPLEMENTED;
179
180 return msg_info->msg_driver->msg_fetch_section_header(msg_info, mime,
181 result, result_len);
182}
183
184int mailmessage_fetch_section_mime(mailmessage * msg_info,
185 struct mailmime * mime,
186 char ** result,
187 size_t * result_len)
188{
189 if (msg_info->msg_driver->msg_fetch_section_mime == NULL)
190 return MAIL_ERROR_NOT_IMPLEMENTED;
191
192 return msg_info->msg_driver->msg_fetch_section_mime(msg_info, mime,
193 result, result_len);
194}
195
196int mailmessage_fetch_section_body(mailmessage * msg_info,
197 struct mailmime * mime,
198 char ** result,
199 size_t * result_len)
200{
201 if (msg_info->msg_driver->msg_fetch_section_body == NULL)
202 return MAIL_ERROR_NOT_IMPLEMENTED;
203
204 return msg_info->msg_driver->msg_fetch_section_body(msg_info, mime,
205 result, result_len);
206}
207
208int mailmessage_fetch_envelope(mailmessage * msg_info,
209 struct mailimf_fields ** result)
210{
211 if (msg_info->msg_driver->msg_fetch_envelope == NULL)
212 return MAIL_ERROR_NOT_IMPLEMENTED;
213
214 return msg_info->msg_driver->msg_fetch_envelope(msg_info, result);
215}
216
217int mailmessage_get_flags(mailmessage * msg_info,
218 struct mail_flags ** result)
219{
220 struct mail_flags * dummy;
221
222 if (msg_info->msg_driver->msg_get_flags == NULL)
223 return MAIL_ERROR_NOT_IMPLEMENTED;
224
225 if (result != NULL)
226 return msg_info->msg_driver->msg_get_flags(msg_info, result);
227 else
228 return msg_info->msg_driver->msg_get_flags(msg_info, &dummy);
229}
230
231void mailmessage_resolve_single_fields(mailmessage * msg_info)
232{
233 if (!msg_info->msg_resolved) {
234 if (msg_info->msg_fields != NULL) {
235 mailimf_single_fields_init(&msg_info->msg_single_fields,
236 msg_info->msg_fields);
237 msg_info->msg_resolved = TRUE;
238 }
239 }
240}
diff --git a/libetpan/src/driver/interface/mailmessage.h b/libetpan/src/driver/interface/mailmessage.h
new file mode 100644
index 0000000..02b351b
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage.h
@@ -0,0 +1,379 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <libetpan/mailmessage_types.h>
37
38#ifndef MAILMESSAGE_H
39
40#define MAILMESSAGE_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mailmessage_new
48
49 This function will initializes a new empty message.
50
51 @return a new empty message will be returned.
52*/
53
54mailmessage * mailmessage_new(void);
55
56/*
57 mailmessage_free
58
59 This function will release the memory used by this message.
60*/
61
62void mailmessage_free(mailmessage * info);
63
64/*
65 mailmessage_init
66
67 This function will initializes a mailmessage structure
68 with a message from a given session.
69
70 @param msg_info This is the message to initialize.
71
72 @param session This is the source session of the message. It
73 can be NULL if the message does not get the information
74 through the session.
75
76 @param driver This is the driver to use for the message.
77
78 @param index This is the message number in the session. 0 can
79 be given if the message is not attached to a session.
80
81 @param size is an optional parameter, 0 can be given.
82 This is informational. This is the size of message content.
83
84 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
85 on error
86*/
87
88int mailmessage_init(mailmessage * msg_info,
89 mailsession * session,
90 mailmessage_driver * driver,
91 uint32_t index, size_t size);
92
93/*
94 mailmessage_flush
95
96 This function will release all the temporary resources that are not
97 necessary to use the mailmessage structure from memory. These
98 resources are for example cached information, such as the MIME
99 structure.
100
101 @param info is the message to clean.
102
103 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
104 on error. We can assume that MAIL_NO_ERROR is always returned.
105*/
106
107int mailmessage_flush(mailmessage * info);
108
109/*
110 mailmessage_check
111
112 This function will notify the new value of the flags to the session,
113 it must be called before mailsession_check_folder() in case the flags have
114 been changed.
115
116 @param info is the message to checkpoint.
117
118 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
119 on error. We can assume that MAIL_NO_ERROR is always returned.
120*/
121
122int mailmessage_check(mailmessage * info);
123
124/*
125 mailmessage_fetch_result_free
126
127 This function releases the memory used by a message returned
128 by any of the fetch function that returns a (char *).
129
130 @param msg_info is the message which the given buffer is from.
131
132 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
133 on error. We can assume that MAIL_NO_ERROR is always returned.
134*/
135
136int mailmessage_fetch_result_free(mailmessage * msg_info,
137 char * msg);
138
139/*
140 mailmessage_fetch
141
142 This function returns the content of the message (headers and text).
143
144 @param msg_info is the message from which we want to fetch information.
145
146 @param result The content of the message is returned in (* result)
147
148 @param result_len The length of the returned string is stored
149 in (* result_len).
150
151 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
152 on error.
153*/
154
155int mailmessage_fetch(mailmessage * msg_info,
156 char ** result,
157 size_t * result_len);
158
159/*
160 mailmessage_fetch_header
161
162 This function returns the header of the message as a string.
163
164 @param msg_info is the message from which we want to fetch information.
165
166 @param result The header of the message is returned in (* result)
167
168 @param result_len The length of the returned string is stored
169 in (* result_len).
170
171 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
172 on error.
173*/
174
175int mailmessage_fetch_header(mailmessage * msg_info,
176 char ** result,
177 size_t * result_len);
178
179/*
180 mailmessage_fetch_body
181
182 This function returns the content of the message (without headers).
183
184 @param msg_info is the message from which we want to fetch information.
185 @param result The message text (without headers) is returned
186 in (* result)
187 @param result_len The length of the returned string is stored
188 in (* result_len).
189
190 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
191 on error.
192*/
193
194int mailmessage_fetch_body(mailmessage * msg_info,
195 char ** result, size_t * result_len);
196
197/*
198 mailmessage_fetch_size
199
200 This function returns the size of the message content.
201
202 @param msg_info is the message from which we want to fetch information.
203
204 @param result The length of the message content is stored in (* result).
205
206 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
207 on error.
208*/
209
210int mailmessage_fetch_size(mailmessage * msg_info,
211 size_t * result);
212
213/*
214 mailmessage_get_bodystructure
215
216 This functions returns the MIME structure of the message.
217 The returned information MUST not be freed by hand. It is freed by
218 mailmessage_flush() or mailmessage_free().
219
220 @param msg_info is the message from which we want to fetch information.
221
222 @param result The MIME structure is stored in (* result).
223
224 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
225 on error.
226*/
227
228int mailmessage_get_bodystructure(mailmessage * msg_info,
229 struct mailmime ** result);
230
231/*
232 mailmessage_fetch_section
233
234 This function returns the content of a MIME part.
235
236 @param msg_info is the message from which we want to fetch information.
237
238 @param mime is the MIME part identifier.
239
240 @param result The content is returned in (* result)
241
242 @param result_len The length of the returned string is stored
243 in (* result_len).
244
245 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
246 on error.
247 */
248
249int mailmessage_fetch_section(mailmessage * msg_info,
250 struct mailmime * mime,
251 char ** result, size_t * result_len);
252
253/*
254 mailmessage_fetch_section_header
255
256 This function returns the header of the message contained
257 in the given MIME part.
258
259 @param msg_info is the message from which we want to fetch information.
260
261 @param mime is the MIME part identifier.
262
263 @param result The header is returned in (* result)
264
265 @param result_len The length of the returned string is stored
266 in (* result_len).
267
268 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
269 on error.
270*/
271
272int mailmessage_fetch_section_header(mailmessage * msg_info,
273 struct mailmime * mime,
274 char ** result,
275 size_t * result_len);
276
277/*
278 mailmessage_fetch_section_mime
279
280 This function returns the MIME header of the given MIME part.
281
282 @param msg_info is the message from which we want to fetch information.
283
284 @param mime is the MIME part identifier.
285
286 @param result The MIME header is returned in (* result)
287
288 @param result_len The length of the returned string is stored
289 in (* result_len).
290
291 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
292 on error.
293*/
294
295int mailmessage_fetch_section_mime(mailmessage * msg_info,
296 struct mailmime * mime,
297 char ** result,
298 size_t * result_len);
299
300/*
301 mailmessage_fetch_section_body
302
303 This function returns the text part of the message contained
304 in the given MIME part.
305
306 @param msg_info is the message from which we want to fetch information.
307
308 @param mime is the MIME part identifier.
309
310 @param result The message text is returned in (* result)
311
312 @param result_len The length of the returned string is stored
313 in (* result_len).
314
315 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
316 on error.
317 */
318
319int mailmessage_fetch_section_body(mailmessage * msg_info,
320 struct mailmime * mime,
321 char ** result,
322 size_t * result_len);
323
324/*
325 mailmessage_fetch_envelope
326
327 This function returns a list of parsed fields of the message,
328 chosen by the driver.
329 The returned structure must be freed with mailimf_fields_free().
330
331 @param msg_info is the message from which we want to fetch information.
332
333 @param result The headers list is returned in (* result)
334
335 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
336 on error.
337 */
338
339int mailmessage_fetch_envelope(mailmessage * msg_info,
340 struct mailimf_fields ** result);
341
342
343/*
344 mailmessage_get_flags
345
346 This function returns the flags related to the message.
347 The returned information MUST not be freed by hand. It is freed by
348 mailmessage_free().
349
350 @param msg_info is the message from which we want to fetch information.
351
352 @param result The flags are stored in (* result).
353
354 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
355 on error.
356*/
357
358int mailmessage_get_flags(mailmessage * msg_info,
359 struct mail_flags ** result);
360
361/*
362 mailmessage_resolve_single_fields
363
364 This function will use the fields information to fill the single_fields
365 structure in the mailmessage structure.
366
367 @param msg_info This is the msg_info to process.
368
369 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
370 on error.
371*/
372
373void mailmessage_resolve_single_fields(mailmessage * msg_info);
374
375#ifdef __cplusplus
376}
377#endif
378
379#endif
diff --git a/libetpan/src/driver/interface/mailmessage_tools.c b/libetpan/src/driver/interface/mailmessage_tools.c
new file mode 100644
index 0000000..9e53173
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_tools.c
@@ -0,0 +1,600 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage_tools.h"
37#include "mailmessage.h"
38
39#include <stdlib.h>
40
41#include "maildriver.h"
42#include "maildriver_tools.h"
43
44int
45mailmessage_generic_initialize(mailmessage * msg_info)
46{
47 struct generic_message_t * msg;
48
49 msg = malloc(sizeof(* msg));
50
51 if (msg == NULL) {
52 return MAIL_ERROR_MEMORY;
53 }
54
55 msg->msg_fetched = 0;
56 msg->msg_message = NULL;
57 msg->msg_length = 0;
58
59 msg->msg_prefetch = NULL;
60 msg->msg_prefetch_free = NULL;
61 msg->msg_data = NULL;
62
63 msg_info->msg_data = msg;
64
65 return MAIL_NO_ERROR;
66}
67
68void mailmessage_generic_flush(mailmessage * msg_info)
69{
70 struct generic_message_t * msg;
71
72 if (msg_info->msg_mime != NULL) {
73 mailmime_free(msg_info->msg_mime);
74 msg_info->msg_mime = NULL;
75 }
76 msg = msg_info->msg_data;
77 if (msg != NULL) {
78 if (msg->msg_prefetch_free != NULL)
79 msg->msg_prefetch_free(msg);
80 msg->msg_fetched = 0;
81 }
82}
83
84void mailmessage_generic_uninitialize(mailmessage * msg_info)
85{
86 struct generic_message_t * msg;
87
88 mailmessage_generic_flush(msg_info);
89
90 msg = msg_info->msg_data;
91 msg_info->msg_data = NULL;
92 free(msg);
93}
94
95static inline int
96mailmessage_generic_prefetch(mailmessage * msg_info)
97{
98 struct generic_message_t * msg;
99 int r;
100
101 msg = msg_info->msg_data;
102
103 if (msg->msg_fetched)
104 return MAIL_NO_ERROR;
105
106#if 0
107 if (msg->message != NULL)
108 return MAIL_NO_ERROR;
109#endif
110
111 r = msg->msg_prefetch(msg_info);
112 if (r != MAIL_NO_ERROR)
113 return r;
114
115 msg->msg_fetched = 1;
116
117 return MAIL_NO_ERROR;
118}
119
120static int
121mailmessage_generic_prefetch_bodystructure(mailmessage * msg_info)
122{
123 size_t length;
124 char * message;
125 size_t cur_token;
126 struct mailmime * mime;
127 int r;
128 int res;
129 struct generic_message_t * msg;
130
131 if (msg_info->msg_mime != NULL) {
132 /* it has already been fetched */
133 return MAIL_NO_ERROR;
134 }
135
136#if 0
137 msg = msg_info->data;
138 if (msg->message == NULL) {
139 r = mailmessage_generic_prefetch(msg_info);
140 if (r != MAIL_NO_ERROR) {
141 res = r;
142 goto err;
143 }
144 }
145#endif
146 r = mailmessage_generic_prefetch(msg_info);
147 if (r != MAIL_NO_ERROR) {
148 res = r;
149 goto err;
150 }
151
152 msg = msg_info->msg_data;
153 message = msg->msg_message;
154 length = msg->msg_length;
155 cur_token = 0;
156 r = mailmime_parse(message, length, &cur_token, &mime);
157 if (r != MAILIMF_NO_ERROR) {
158 res = MAIL_ERROR_PARSE;
159 goto err;
160 }
161
162 msg_info->msg_mime = mime;
163
164 return MAIL_NO_ERROR;
165
166 err:
167 return res;
168}
169
170void
171mailmessage_generic_fetch_result_free(mailmessage * msg_info, char * msg)
172{
173 int r;
174
175 r = mmap_string_unref(msg);
176}
177
178int mailmessage_generic_fetch(mailmessage * msg_info,
179 char ** result,
180 size_t * result_len)
181{
182 int r;
183 char * message;
184 size_t cur_token;
185 size_t length;
186 MMAPString * mmapstr;
187 int res;
188 struct generic_message_t * msg;
189
190 msg = msg_info->msg_data;
191 r = mailmessage_generic_prefetch(msg_info);
192 if (r != MAIL_NO_ERROR) {
193 res = r;
194 goto err;
195 }
196
197 message = msg->msg_message;
198 length = msg->msg_length;
199 cur_token = 0;
200
201 mmapstr = mmap_string_new_len(message, length);
202 if (mmapstr == NULL) {
203 res = MAIL_ERROR_MEMORY;
204 goto err;
205 }
206
207 r = mmap_string_ref(mmapstr);
208 if (r < 0) {
209 res = MAIL_ERROR_MEMORY;
210 goto free_mmap;
211 }
212
213 * result = mmapstr->str;
214 * result_len = length;
215
216 return MAIL_NO_ERROR;
217
218 free_mmap:
219 mmap_string_free(mmapstr);
220 err:
221 return res;
222}
223
224int mailmessage_generic_fetch_header(mailmessage * msg_info,
225 char ** result,
226 size_t * result_len)
227{
228 int r;
229 char * message;
230 size_t cur_token;
231 size_t length;
232 MMAPString * mmapstr;
233 char * headers;
234 int res;
235 struct generic_message_t * msg;
236
237 msg = msg_info->msg_data;
238 r = mailmessage_generic_prefetch(msg_info);
239 if (r != MAIL_NO_ERROR) {
240 res = r;
241 goto err;
242 }
243
244 message = msg->msg_message;
245 length = msg->msg_length;
246 cur_token = 0;
247
248 while (1) {
249 r = mailimf_ignore_field_parse(message, length, &cur_token);
250 if (r == MAILIMF_NO_ERROR) {
251 /* do nothing */
252 }
253 else
254 break;
255 }
256 mailimf_crlf_parse(message, length, &cur_token);
257
258 mmapstr = mmap_string_new_len(message, cur_token);
259 if (mmapstr == NULL) {
260 res = MAIL_ERROR_MEMORY;
261 goto err;
262 }
263
264 r = mmap_string_ref(mmapstr);
265 if (r < 0) {
266 res = MAIL_ERROR_MEMORY;
267 goto free_mmap;
268 }
269
270 headers = mmapstr->str;
271
272 * result = headers;
273 * result_len = cur_token;
274
275 return MAIL_NO_ERROR;
276
277 free_mmap:
278 mmap_string_free(mmapstr);
279 err:
280 return res;
281}
282
283int mailmessage_generic_fetch_body(mailmessage * msg_info,
284 char ** result, size_t * result_len)
285{
286 int r;
287 char * message;
288 size_t cur_token;
289 MMAPString * mmapstr;
290 size_t length;
291 int res;
292 struct generic_message_t * msg;
293
294 msg = msg_info->msg_data;
295 r = mailmessage_generic_prefetch(msg_info);
296 if (r != MAIL_NO_ERROR) {
297 res = r;
298 goto err;
299 }
300
301 message = msg->msg_message;
302 length = msg->msg_length;
303 cur_token = 0;
304
305 while (1) {
306 r = mailimf_ignore_field_parse(message, length, &cur_token);
307 if (r == MAILIMF_NO_ERROR) {
308 /* do nothing */
309 }
310 else
311 break;
312 }
313 mailimf_crlf_parse(message, length, &cur_token);
314
315 mmapstr = mmap_string_new_len(message + cur_token, length - cur_token);
316 if (mmapstr == NULL) {
317 res = MAIL_ERROR_MEMORY;
318 goto err;
319 }
320
321 r = mmap_string_ref(mmapstr);
322 if (r < 0) {
323 res = MAIL_ERROR_MEMORY;
324 goto free_mmap;
325 }
326
327 * result = mmapstr->str;
328 * result_len = length - cur_token;
329
330 return MAIL_NO_ERROR;
331
332 free_mmap:
333 mmap_string_free(mmapstr);
334 err:
335 return res;
336}
337
338
339
340
341int
342mailmessage_generic_get_bodystructure(mailmessage * msg_info,
343 struct mailmime ** result)
344{
345 int r;
346
347 r = mailmessage_generic_prefetch_bodystructure(msg_info);
348 if (r != MAIL_NO_ERROR)
349 return r;
350
351 * result = msg_info->msg_mime;
352
353 return MAIL_NO_ERROR;
354}
355
356
357
358
359int
360mailmessage_generic_fetch_section(mailmessage * msg_info,
361 struct mailmime * mime,
362 char ** result, size_t * result_len)
363{
364 MMAPString * mmapstr;
365 int r;
366 int res;
367
368 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data,
369 mime->mm_body->dt_data.dt_text.dt_length);
370 if (mmapstr == NULL) {
371 res = MAIL_ERROR_MEMORY;
372 goto err;
373 }
374
375 r = mmap_string_ref(mmapstr);
376 if (r < 0) {
377 res = MAIL_ERROR_MEMORY;
378 goto free_mmap;
379 }
380
381 * result = mmapstr->str;
382 * result_len = mmapstr->len;
383
384 return MAIL_NO_ERROR;
385
386 free_mmap:
387 mmap_string_free(mmapstr);
388 err:
389 return res;
390}
391
392int
393mailmessage_generic_fetch_section_header(mailmessage * msg_info,
394 struct mailmime * mime,
395 char ** result,
396 size_t * result_len)
397{
398 MMAPString * mmapstr;
399 int r;
400 int res;
401 size_t cur_token;
402
403 /* skip mime */
404
405 cur_token = 0;
406
407 if (mime->mm_type == MAILMIME_MESSAGE) {
408
409 while (1) {
410 r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data,
411 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
412 if (r == MAILIMF_NO_ERROR) {
413 /* do nothing */
414 }
415 else
416 break;
417 }
418
419 r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data,
420 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
421 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
422 res = maildriver_imf_error_to_mail_error(r);
423 goto err;
424 }
425 }
426
427 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data,
428 cur_token);
429 if (mmapstr == NULL) {
430 res = MAIL_ERROR_MEMORY;
431 goto err;
432 }
433
434 r = mmap_string_ref(mmapstr);
435 if (r < 0) {
436 res = MAIL_ERROR_MEMORY;
437 goto free_mmap;
438 }
439
440 * result = mmapstr->str;
441 * result_len = mmapstr->len;
442
443 return MAIL_NO_ERROR;
444
445 free_mmap:
446 mmap_string_free(mmapstr);
447 err:
448 return res;
449}
450
451int
452mailmessage_generic_fetch_section_mime(mailmessage * msg_info,
453 struct mailmime * mime,
454 char ** result,
455 size_t * result_len)
456{
457 MMAPString * mmapstr;
458 int r;
459 int res;
460 size_t cur_token;
461
462 cur_token = 0;
463
464 /* skip header */
465
466 while (1) {
467 r = mailimf_ignore_field_parse(mime->mm_mime_start,
468 mime->mm_length, &cur_token);
469 if (r == MAILIMF_NO_ERROR) {
470 /* do nothing */
471 }
472 else
473 break;
474 }
475
476 r = mailimf_crlf_parse(mime->mm_mime_start, mime->mm_length, &cur_token);
477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
478 res = maildriver_imf_error_to_mail_error(r);
479 goto err;
480 }
481
482 mmapstr = mmap_string_new_len(mime->mm_mime_start, cur_token);
483 if (mmapstr == NULL) {
484 res = MAIL_ERROR_MEMORY;
485 goto err;
486 }
487
488 r = mmap_string_ref(mmapstr);
489 if (r < 0) {
490 res = MAIL_ERROR_MEMORY;
491 goto free_mmap;
492 }
493
494 * result = mmapstr->str;
495 * result_len = mmapstr->len;
496
497 return MAIL_NO_ERROR;
498
499 free_mmap:
500 mmap_string_free(mmapstr);
501 err:
502 return res;
503}
504
505int
506mailmessage_generic_fetch_section_body(mailmessage * msg_info,
507 struct mailmime * mime,
508 char ** result,
509 size_t * result_len)
510{
511 MMAPString * mmapstr;
512 int r;
513 int res;
514 size_t cur_token;
515
516 cur_token = 0;
517
518 if (mime->mm_type == MAILMIME_MESSAGE) {
519
520 /* skip header */
521
522 while (1) {
523 r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data,
524 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
525 if (r == MAILIMF_NO_ERROR) {
526 /* do nothing */
527 }
528 else
529 break;
530 }
531
532 r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data,
533 mime->mm_body->dt_data.dt_text.dt_length, &cur_token);
534 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
535 res = maildriver_imf_error_to_mail_error(r);
536 goto err;
537 }
538 }
539
540 mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data +
541 cur_token, mime->mm_body->dt_data.dt_text.dt_length - cur_token);
542 if (mmapstr == NULL) {
543 res = MAIL_ERROR_MEMORY;
544 goto err;
545 }
546
547 r = mmap_string_ref(mmapstr);
548 if (r < 0) {
549 res = MAIL_ERROR_MEMORY;
550 goto free_mmap;
551 }
552
553 * result = mmapstr->str;
554 * result_len = mmapstr->len;
555
556 return MAIL_NO_ERROR;
557
558 free_mmap:
559 mmap_string_free(mmapstr);
560 err:
561 return res;
562}
563
564int mailmessage_generic_fetch_envelope(mailmessage * msg_info,
565 struct mailimf_fields ** result)
566{
567 int r;
568 int res;
569 size_t cur_token;
570 char * header;
571 size_t length;
572 struct mailimf_fields * fields;
573
574 r = mailmessage_fetch_header(msg_info, &header, &length);
575 if (r != MAIL_NO_ERROR) {
576 res = r;
577 goto err;
578 }
579
580 cur_token = 0;
581
582 r = mailimf_envelope_fields_parse(header, length, &cur_token,
583 &fields);
584 if (r != MAILIMF_NO_ERROR) {
585 res = maildriver_imf_error_to_mail_error(r);
586 goto free;
587 /* do nothing */
588 }
589
590 mailmessage_fetch_result_free(msg_info, header);
591
592 * result = fields;
593
594 return MAIL_NO_ERROR;
595
596 free:
597 mailmessage_fetch_result_free(msg_info, header);
598 err:
599 return res;
600}
diff --git a/libetpan/src/driver/interface/mailmessage_tools.h b/libetpan/src/driver/interface/mailmessage_tools.h
new file mode 100644
index 0000000..fd055c7
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_tools.h
@@ -0,0 +1,103 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMESSAGE_TOOLS_H
37
38#define MAILMESSAGE_TOOLS_H
39
40#include "mailmessage_types.h"
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46int
47mailmessage_generic_initialize(mailmessage *
48 msg_info);
49
50void mailmessage_generic_uninitialize(mailmessage *
51 msg_info);
52
53void mailmessage_generic_flush(mailmessage * msg_info);
54
55void mailmessage_generic_fetch_result_free(mailmessage * msg_info,
56 char * msg);
57
58int mailmessage_generic_fetch(mailmessage * msg_info,
59 char ** result,
60 size_t * result_len);
61
62int mailmessage_generic_fetch_header(mailmessage * msg_info,
63 char ** result,
64 size_t * result_len);
65
66int mailmessage_generic_fetch_body(mailmessage * msg_info,
67 char ** result, size_t * result_len);
68
69int mailmessage_generic_get_bodystructure(mailmessage *
70 msg_info,
71 struct mailmime ** result);
72
73int
74mailmessage_generic_fetch_section(mailmessage * msg_info,
75 struct mailmime * mime,
76 char ** result, size_t * result_len);
77
78int
79mailmessage_generic_fetch_section_header(mailmessage * msg_info,
80 struct mailmime * mime,
81 char ** result,
82 size_t * result_len);
83
84int
85mailmessage_generic_fetch_section_mime(mailmessage * msg_info,
86 struct mailmime * mime,
87 char ** result,
88 size_t * result_len);
89
90int
91mailmessage_generic_fetch_section_body(mailmessage * msg_info,
92 struct mailmime * mime,
93 char ** result,
94 size_t * result_len);
95
96int mailmessage_generic_fetch_envelope(mailmessage * msg_info,
97 struct mailimf_fields ** result);
98
99#ifdef __cplusplus
100}
101#endif
102
103#endif
diff --git a/libetpan/src/driver/interface/mailmessage_types.c b/libetpan/src/driver/interface/mailmessage_types.c
new file mode 100644
index 0000000..e0955e4
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_types.c
@@ -0,0 +1,92 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmessage_types.h"
37
38#include "mail.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43mailmessage * mailmessage_new(void)
44{
45 mailmessage * msg_info;
46
47 msg_info = malloc(sizeof(* msg_info));
48 if (msg_info == NULL)
49 goto err;
50
51 msg_info->msg_driver = NULL;
52 msg_info->msg_session = NULL;
53 msg_info->msg_index = 0;
54 msg_info->msg_uid = NULL;
55
56 msg_info->msg_cached = FALSE;
57 msg_info->msg_size = 0;
58 msg_info->msg_fields = NULL;
59 memset(&msg_info->msg_single_fields,
60 0, sizeof(struct mailimf_single_fields));
61 msg_info->msg_resolved = FALSE;
62 msg_info->msg_flags = NULL;
63
64 msg_info->msg_mime = NULL;
65 msg_info->msg_data = NULL;
66
67 msg_info->msg_folder = NULL;
68 msg_info->msg_user_data = NULL;
69
70 return msg_info;
71
72 err:
73 return NULL;
74}
75
76void mailmessage_free(mailmessage * msg_info)
77{
78 if (msg_info->msg_driver != NULL) {
79 if (msg_info->msg_driver->msg_uninitialize != NULL)
80 msg_info->msg_driver->msg_uninitialize(msg_info);
81 }
82
83 if (msg_info->msg_fields != NULL)
84 mailimf_fields_free(msg_info->msg_fields);
85 if (msg_info->msg_mime != NULL)
86 mailmime_free(msg_info->msg_mime);
87 if (msg_info->msg_flags != NULL)
88 mail_flags_free(msg_info->msg_flags);
89 if (msg_info->msg_uid != NULL)
90 free(msg_info->msg_uid);
91 free(msg_info);
92}
diff --git a/libetpan/src/driver/interface/mailmessage_types.h b/libetpan/src/driver/interface/mailmessage_types.h
new file mode 100644
index 0000000..c3ed2c4
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailmessage_types.h
@@ -0,0 +1,50 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMESSAGE_TYPES_H
37
38#define MAILMESSAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#ifdef __cplusplus
47}
48#endif
49
50#endif
diff --git a/libetpan/src/driver/interface/mailstorage.c b/libetpan/src/driver/interface/mailstorage.c
new file mode 100644
index 0000000..2e2ddcb
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage.c
@@ -0,0 +1,341 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage.h"
37
38#include "maildriver.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43static int mailstorage_get_folder(struct mailstorage * storage,
44 char * pathname, mailsession ** result);
45
46struct mailfolder * mailfolder_new(struct mailstorage * storage,
47 char * pathname, char * virtual_name)
48{
49 struct mailfolder * folder;
50
51 folder = malloc(sizeof(struct mailfolder));
52 if (folder == NULL)
53 goto err;
54
55 if (pathname != NULL) {
56 folder->fld_pathname = strdup(pathname);
57 if (folder->fld_pathname == NULL)
58 goto free;
59 }
60 else
61 folder->fld_pathname = NULL;
62
63 if (virtual_name != NULL) {
64 folder->fld_virtual_name = strdup(virtual_name);
65 if (folder->fld_virtual_name == NULL)
66 goto free_pathname;
67 }
68 else
69 folder->fld_virtual_name = NULL;
70
71 folder->fld_storage = storage;
72
73 folder->fld_session = NULL;
74 folder->fld_shared_session = 0;
75 folder->fld_pos = NULL;
76
77 folder->fld_parent = NULL;
78 folder->fld_sibling_index = 0;
79 folder->fld_children = carray_new(128);
80 if (folder->fld_children == NULL)
81 goto free_virtualname;
82
83 return folder;
84
85free_virtualname:
86 if (folder->fld_virtual_name != NULL)
87 free(folder->fld_virtual_name);
88free_pathname:
89 if (folder->fld_pathname != NULL)
90 free(folder->fld_pathname);
91free:
92 free(folder);
93err:
94 return NULL;
95}
96
97void mailfolder_free(struct mailfolder * folder)
98{
99 if (folder->fld_parent != NULL)
100 mailfolder_detach_parent(folder);
101
102 while (carray_count(folder->fld_children) > 0) {
103 struct mailfolder * child;
104
105 child = carray_get(folder->fld_children, 0);
106 mailfolder_detach_parent(child);
107 }
108
109 carray_free(folder->fld_children);
110
111 if (folder->fld_session != NULL)
112 mailfolder_disconnect(folder);
113
114 if (folder->fld_virtual_name != NULL)
115 free(folder->fld_virtual_name);
116 if (folder->fld_pathname != NULL)
117 free(folder->fld_pathname);
118 free(folder);
119}
120
121int mailfolder_connect(struct mailfolder * folder)
122{
123 mailsession * session;
124 int res;
125 int r;
126
127 if (folder->fld_storage == NULL) {
128 res = MAIL_ERROR_INVAL;
129 goto err;
130 }
131
132 if (folder->fld_storage->sto_session == NULL) {
133 r = mailstorage_connect(folder->fld_storage);
134 if (r != MAIL_NO_ERROR) {
135 res = r;
136 goto err;
137 }
138 }
139
140 if (folder->fld_session != NULL) {
141 if ((folder->fld_pathname != NULL) && (folder->fld_shared_session)) {
142 if (folder->fld_session->sess_driver->sess_select_folder != NULL) {
143 r = mailsession_select_folder(folder->fld_session,
144 folder->fld_pathname);
145 if (r != MAIL_NO_ERROR) {
146 res = r;
147 goto err;
148 }
149 }
150 }
151
152 return MAIL_NO_ERROR;
153 }
154
155 r = mailstorage_get_folder(folder->fld_storage, folder->fld_pathname,
156 &session);
157 if (r != MAIL_NO_ERROR) {
158 res = r;
159 goto err;
160 }
161 folder->fld_session = session;
162 folder->fld_shared_session = (session == folder->fld_storage->sto_session);
163 if (folder->fld_shared_session) {
164 r = clist_append(folder->fld_storage->sto_shared_folders, folder);
165 if (r < 0) {
166 folder->fld_session = NULL;
167 res = MAIL_ERROR_MEMORY;
168 goto err;
169 }
170 folder->fld_pos = clist_end(folder->fld_storage->sto_shared_folders);
171 }
172
173 return MAIL_NO_ERROR;
174
175err:
176 return res;
177}
178
179void mailfolder_disconnect(struct mailfolder * folder)
180{
181 if (folder->fld_session == NULL)
182 return;
183
184 if (folder->fld_shared_session) {
185 clist_delete(folder->fld_storage->sto_shared_folders, folder->fld_pos);
186 folder->fld_pos = NULL;
187 }
188 else {
189 mailsession_logout(folder->fld_session);
190 mailsession_free(folder->fld_session);
191 }
192
193 folder->fld_session = NULL;
194}
195
196int mailfolder_add_child(struct mailfolder * parent,
197 struct mailfolder * child)
198{
199 unsigned int index;
200 int r;
201
202 r = carray_add(parent->fld_children, child, &index);
203 if (r < 0)
204 return MAIL_ERROR_MEMORY;
205
206 child->fld_sibling_index = index;
207 child->fld_parent = parent;
208
209 return MAIL_NO_ERROR;
210}
211
212int mailfolder_detach_parent(struct mailfolder * folder)
213{
214 unsigned int i;
215 int r;
216
217 if (folder->fld_parent == NULL)
218 return MAIL_ERROR_INVAL;
219
220 r = carray_delete_slow(folder->fld_parent->fld_children,
221 folder->fld_sibling_index);
222 if (r < 0)
223 return MAIL_ERROR_INVAL;
224
225 for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) {
226 struct mailfolder * child;
227
228 child = carray_get(folder->fld_parent->fld_children, i);
229 child->fld_sibling_index = i;
230 }
231
232 folder->fld_parent = NULL;
233 folder->fld_sibling_index = 0;
234
235 return MAIL_NO_ERROR;
236}
237
238struct mailstorage * mailstorage_new(char * sto_id)
239{
240 struct mailstorage * storage;
241
242 storage = malloc(sizeof(struct mailstorage));
243 if (storage == NULL)
244 goto err;
245
246 if (sto_id != NULL) {
247 storage->sto_id = strdup(sto_id);
248 if (storage->sto_id == NULL)
249 goto free;
250 }
251 else
252 storage->sto_id = NULL;
253
254 storage->sto_data = NULL;
255 storage->sto_session = NULL;
256 storage->sto_driver = NULL;
257 storage->sto_shared_folders = clist_new();
258 if (storage->sto_shared_folders == NULL)
259 goto free_id;
260
261 return storage;
262
263 free_id:
264 if (storage->sto_id != NULL)
265 free(storage->sto_id);
266 free:
267 free(storage);
268 err:
269 return NULL;
270}
271
272void mailstorage_free(struct mailstorage * storage)
273{
274 if (storage->sto_session != NULL)
275 mailstorage_disconnect(storage);
276
277 if (storage->sto_driver != NULL) {
278 if (storage->sto_driver->sto_uninitialize != NULL)
279 storage->sto_driver->sto_uninitialize(storage);
280 }
281
282 clist_free(storage->sto_shared_folders);
283
284 if (storage->sto_id != NULL)
285 free(storage->sto_id);
286
287 free(storage);
288}
289
290int mailstorage_connect(struct mailstorage * storage)
291{
292 if (storage->sto_session != NULL)
293 return MAIL_NO_ERROR;
294
295 if (!clist_isempty(storage->sto_shared_folders))
296 return MAIL_ERROR_BAD_STATE;
297
298 if (storage->sto_driver->sto_connect == NULL)
299 return MAIL_ERROR_NOT_IMPLEMENTED;
300
301 return storage->sto_driver->sto_connect(storage);
302}
303
304
305void mailstorage_disconnect(struct mailstorage * storage)
306{
307 int r;
308 clistiter * cur;
309
310 while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) {
311 struct mailfolder * folder;
312
313 folder = cur->data;
314 mailfolder_disconnect(folder);
315 }
316
317 if (storage->sto_session == NULL)
318 return;
319
320 r = mailsession_logout(storage->sto_session);
321
322 mailsession_free(storage->sto_session);
323 storage->sto_session = NULL;
324}
325
326
327int mailstorage_noop(struct mailstorage * storage)
328{
329 return mailsession_noop(storage->sto_session);
330}
331
332
333static int mailstorage_get_folder(struct mailstorage * storage,
334 char * pathname, mailsession ** result)
335{
336 if (storage->sto_driver->sto_get_folder_session == NULL)
337 return MAIL_ERROR_NOT_IMPLEMENTED;
338
339 return storage->sto_driver->sto_get_folder_session(storage,
340 pathname, result);
341}
diff --git a/libetpan/src/driver/interface/mailstorage.h b/libetpan/src/driver/interface/mailstorage.h
new file mode 100644
index 0000000..e8cbda3
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage.h
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_STORAGE_H
37
38#define MAIL_STORAGE_H
39
40#include <libetpan/maildriver_types.h>
41#include <libetpan/mailstorage_types.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47/* storage */
48
49/*
50 mailstorage_new
51
52 This function creates an empty storage. This storage have to be initialized.
53 The "driver" and "data" fields should be initialized.
54
55 @param id is the name of the storage. It can be NULL.
56 The given parameter is no more needed when the creation is finished.
57 The given string is duplicated.
58
59 @return The mail storage is returned.
60*/
61
62struct mailstorage * mailstorage_new(char * sto_id);
63
64void mailstorage_free(struct mailstorage * storage);
65
66/*
67 session will be initialized on success.
68*/
69
70int mailstorage_connect(struct mailstorage * storage);
71
72void mailstorage_disconnect(struct mailstorage * storage);
73
74int mailstorage_noop(struct mailstorage * storage);
75
76
77/* folder */
78
79struct mailfolder * mailfolder_new(struct mailstorage * fld_storage,
80 char * fld_pathname, char * fld_virtual_name);
81
82void mailfolder_free(struct mailfolder * folder);
83
84int mailfolder_add_child(struct mailfolder * parent,
85 struct mailfolder * child);
86
87int mailfolder_detach_parent(struct mailfolder * folder);
88
89int mailfolder_connect(struct mailfolder * folder);
90
91void mailfolder_disconnect(struct mailfolder * folder);
92
93#ifdef __cplusplus
94}
95#endif
96
97#endif
98
99
diff --git a/libetpan/src/driver/interface/mailstorage_tools.c b/libetpan/src/driver/interface/mailstorage_tools.c
new file mode 100644
index 0000000..9d39cab
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_tools.c
@@ -0,0 +1,372 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage_tools.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <netdb.h>
42#include <netinet/in.h>
43#include <sys/socket.h>
44#include <unistd.h>
45#include <stdlib.h>
46#include <sys/wait.h>
47#include <sys/ioctl.h>
48#include <fcntl.h>
49#include <string.h>
50
51#include "mail.h"
52#include "mailmessage.h"
53#include "maildriver.h"
54
55/* tools */
56
57/* connection to TCP/IP server */
58
59static int tcp_connect(char * server, uint16_t port)
60{
61 struct hostent * remotehost;
62 struct sockaddr_in sa;
63 int s;
64 int r;
65
66 s = socket(PF_INET, SOCK_STREAM, 0);
67 if (s == -1)
68 goto err;
69
70 remotehost = gethostbyname(server);
71 if (remotehost == NULL)
72 goto close_socket;
73
74 sa.sin_family = AF_INET;
75 sa.sin_port = htons(port);
76 memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length);
77
78 r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
79 if (r == -1)
80 goto close_socket;
81
82 return s;
83
84 close_socket:
85 close(s);
86 err:
87 return -1;
88}
89
90
91/* connection through a shell command */
92
93static void do_exec_command(int fd, const char *command,
94 char *servername, uint16_t port)
95{
96 int i, maxopen;
97
98 if (fork() > 0) {
99 /* Fork again to become a child of init rather than
100 the etpan client. */
101 exit(0);
102 }
103
104 if (servername)
105 setenv("ETPANSERVER", servername, 1);
106 else
107 unsetenv("ETPANSERVER");
108
109 if (port) {
110 char porttext[20];
111
112 snprintf(porttext, sizeof(porttext), "%d", port);
113 setenv("ETPANPORT", porttext, 1);
114 }
115 else {
116 unsetenv("ETPANPORT");
117 }
118
119 /* Not a lot we can do if there's an error other than bail. */
120 if (dup2(fd, 0) == -1)
121 exit(1);
122 if (dup2(fd, 1) == -1)
123 exit(1);
124
125 /* Should we close stderr and reopen /dev/null? */
126
127 maxopen = sysconf(_SC_OPEN_MAX);
128 for (i=3; i < maxopen; i++)
129 close(i);
130
131#ifdef TIOCNOTTY
132 /* Detach from the controlling tty if we have one. Otherwise,
133 SSH might do something stupid like trying to use it instead
134 of running $SSH_ASKPASS. Doh. */
135 fd = open("/dev/tty", O_RDONLY);
136 if (fd != -1) {
137 ioctl(fd, TIOCNOTTY, NULL);
138 close(fd);
139 }
140#endif /* TIOCNOTTY */
141
142 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
143
144 /* Eep. Shouldn't reach this */
145 exit(1);
146}
147
148static int subcommand_connect(char *command, char *servername, uint16_t port)
149{
150 int sockfds[2];
151 pid_t childpid;
152
153 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
154 return -1;
155
156 childpid = fork();
157 if (!childpid) {
158 do_exec_command(sockfds[1], command, servername, port);
159 }
160 else if (childpid == -1) {
161 close(sockfds[0]);
162 close(sockfds[1]);
163 return -1;
164 }
165
166 close(sockfds[1]);
167
168 /* Reap child, leaving grandchild process to run */
169 waitpid(childpid, NULL, 0);
170
171 return sockfds[0];
172}
173
174int mailstorage_generic_connect(mailsession_driver * driver,
175 char * servername,
176 uint16_t port,
177 char * command,
178 int connection_type,
179 int cache_function_id,
180 char * cache_directory,
181 int flags_function_id,
182 char * flags_directory,
183 mailsession ** result)
184{
185 int r;
186 int res;
187 mailstream * stream;
188 int fd;
189 mailsession * session;
190 int connect_result;
191
192 switch (connection_type) {
193 case CONNECTION_TYPE_PLAIN:
194 case CONNECTION_TYPE_TRY_STARTTLS:
195 case CONNECTION_TYPE_STARTTLS:
196 case CONNECTION_TYPE_TLS:
197 fd = tcp_connect(servername, port);
198 if (fd == -1) {
199 res = MAIL_ERROR_CONNECT;
200 goto err;
201 }
202 break;
203
204 case CONNECTION_TYPE_COMMAND:
205 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
206 case CONNECTION_TYPE_COMMAND_STARTTLS:
207 case CONNECTION_TYPE_COMMAND_TLS:
208 fd = subcommand_connect(command, servername, port);
209 break;
210
211 default:
212 fd = -1;
213 break;
214 }
215
216 if (fd == -1) {
217 res = MAIL_ERROR_INVAL;
218 goto err;
219 }
220
221 switch (connection_type) {
222 case CONNECTION_TYPE_PLAIN:
223 case CONNECTION_TYPE_TRY_STARTTLS:
224 case CONNECTION_TYPE_STARTTLS:
225 case CONNECTION_TYPE_COMMAND:
226 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
227 case CONNECTION_TYPE_COMMAND_STARTTLS:
228 stream = mailstream_socket_open(fd);
229 break;
230
231 case CONNECTION_TYPE_TLS:
232 case CONNECTION_TYPE_COMMAND_TLS:
233 stream = mailstream_ssl_open(fd);
234 break;
235
236 default:
237 stream = NULL;
238 break;
239 }
240
241 if (stream == NULL) {
242 res = MAIL_ERROR_STREAM;
243 close(fd);
244 goto err;
245 }
246
247 session = mailsession_new(driver);
248 if (session == NULL) {
249 res = MAIL_ERROR_MEMORY;
250 goto close_stream;
251 }
252
253 if (cache_directory != NULL) {
254 char cache_directory_server[PATH_MAX];
255
256 snprintf(cache_directory_server, PATH_MAX, "%s/%s",
257 cache_directory, servername);
258
259 r = mailsession_parameters(session,
260 cache_function_id,
261 cache_directory_server);
262 if (r != MAIL_NO_ERROR) {
263 res = r;
264 goto close_stream;
265 }
266 }
267
268 if (flags_directory != NULL) {
269 char flags_directory_server[PATH_MAX];
270
271 snprintf(flags_directory_server, PATH_MAX, "%s/%s",
272 flags_directory, servername);
273
274 r = mailsession_parameters(session,
275 flags_function_id,
276 flags_directory_server);
277 if (r != MAIL_NO_ERROR) {
278 res = r;
279 goto close_stream;
280 }
281 }
282
283 r = mailsession_connect_stream(session, stream);
284 switch (r) {
285 case MAIL_NO_ERROR_NON_AUTHENTICATED:
286 case MAIL_NO_ERROR_AUTHENTICATED:
287 case MAIL_NO_ERROR:
288 break;
289 default:
290 res = r;
291 goto free;
292 }
293
294 connect_result = r;
295
296 switch (connection_type) {
297 case CONNECTION_TYPE_TRY_STARTTLS:
298 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
299 r = mailsession_starttls(session);
300 if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) {
301 res = r;
302 goto free;
303 }
304 break;
305
306 case CONNECTION_TYPE_STARTTLS:
307 case CONNECTION_TYPE_COMMAND_STARTTLS:
308 r = mailsession_starttls(session);
309 if (r != MAIL_NO_ERROR) {
310 res = r;
311 goto free;
312 }
313 }
314
315 * result = session;
316
317 return connect_result;
318
319 close_stream:
320 mailstream_close(stream);
321 free:
322 mailsession_free(session);
323 err:
324 return res;
325}
326
327
328
329
330
331int mailstorage_generic_auth(mailsession * session,
332 int connect_result,
333 int auth_type,
334 char * login,
335 char * password)
336{
337 int must_auth;
338 int r;
339 int res;
340
341 r = connect_result;
342
343 must_auth = FALSE;
344 switch (r) {
345 case MAIL_NO_ERROR_NON_AUTHENTICATED:
346 must_auth = TRUE;
347 break;
348 case MAIL_NO_ERROR_AUTHENTICATED:
349 case MAIL_NO_ERROR:
350 break;
351 default:
352 res = r;
353 goto err;
354 }
355
356 if ((login == NULL) || (password == NULL))
357 must_auth = FALSE;
358
359 if (must_auth) {
360 r = mailsession_login(session, login, password);
361 if (r != MAIL_NO_ERROR) {
362 mailsession_logout(session);
363 res = r;
364 goto err;
365 }
366 }
367
368 return MAIL_NO_ERROR;
369
370 err:
371 return res;
372}
diff --git a/libetpan/src/driver/interface/mailstorage_tools.h b/libetpan/src/driver/interface/mailstorage_tools.h
new file mode 100644
index 0000000..113dcdf
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_tools.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstorage.h"
37
38#ifndef MAILSTORAGE_TOOLS_H
39
40#define MAILSTORAGE_TOOLS_H
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46int mailstorage_generic_connect(mailsession_driver * driver,
47 char * servername,
48 uint16_t port,
49 char * command,
50 int connection_type,
51 int cache_function_id,
52 char * cache_directory,
53 int flags_function_id,
54 char * flags_directory,
55 mailsession ** result);
56
57int mailstorage_generic_auth(mailsession * session,
58 int connect_result,
59 int auth_type,
60 char * login,
61 char * password);
62
63#ifdef __cplusplus
64}
65#endif
66
67#endif
diff --git a/libetpan/src/driver/interface/mailstorage_types.h b/libetpan/src/driver/interface/mailstorage_types.h
new file mode 100644
index 0000000..d0d18c8
--- a/dev/null
+++ b/libetpan/src/driver/interface/mailstorage_types.h
@@ -0,0 +1,203 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSTORAGE_TYPES_H
37
38#define MAILSTORAGE_TYPES_H
39
40#include <libetpan/maildriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46struct mailstorage;
47
48typedef struct mailstorage_driver mailstorage_driver;
49
50
51/*
52 There is three kinds of identities :
53 - storage
54 - folders
55 - session
56
57 A storage (struct mailstorage) represents whether a server or
58 a main path,
59
60 A storage can be an IMAP server, the root path of a MH or a mbox file.
61
62 Folders (struct mailfolder) are the mailboxes we can
63 choose in the server or as sub-folder of the main path.
64
65 Folders for IMAP are the IMAP mailboxes, for MH this is one of the
66 folder of the MH storage, for mbox, there is only one folder, the
67 mbox file content;
68
69 A mail session (struct mailsession) is whether a connection to a server
70 or a path that is open. It is the abstraction lower folders and storage.
71 It allow us to send commands.
72
73 We have a session driver for mail session for each kind of storage.
74
75 From a session, we can get a message (struct mailmessage) to read.
76 We have a message driver for each kind of storage.
77*/
78
79/*
80 mailstorage_driver is the driver structure for mail storages
81
82 - name is the name of the driver
83
84 - connect() connects the storage to the remote access or to
85 the path in the local filesystem.
86
87 - get_folder() can have two kinds of behaviour.
88 Either it creates a new session and independant from the session
89 used by the storage and select the given mailbox or
90 it selects the given mailbox in the current session.
91 It depends on the efficiency of the mail driver.
92
93 - uninitialize() frees the data created with mailstorage constructor.
94*/
95
96struct mailstorage_driver {
97 char * sto_name;
98 int (* sto_connect)(struct mailstorage * storage);
99 int (* sto_get_folder_session)(struct mailstorage * storage,
100 char * pathname, mailsession ** result);
101 void (* sto_uninitialize)(struct mailstorage * storage);
102};
103
104/*
105 mailstorage is the data structure for a storage
106
107 - id is the name of the storage, it can be NULL.
108
109 - data is the data specific to the driver.
110 This is the internal state of the storage.
111
112 - session is the session related to the storage.
113
114 - driver is the driver for the storage.
115
116 - shared_folders is the list of folders returned by the storage.
117*/
118
119struct mailstorage {
120 char * sto_id;
121 void * sto_data;
122 mailsession * sto_session;
123 mailstorage_driver * sto_driver;
124 clist * sto_shared_folders; /* list of (struct mailfolder *) */
125
126 void * sto_user_data;
127};
128
129
130
131/*
132 mailfolder is the data structure for a mailbox
133
134 - pathname is the path of the mailbox on the storage
135
136 - virtual_name is the folder identifier, it can be a path,
137 a name or NULL.
138
139 - storage is the storage to which the folder belongs to.
140
141 - session is the session related to the folder. It can be
142 different of the session of the storage.
143
144 - shared_session is != 0 if the session is the same as the
145 session of the storage.
146
147 - pos is the position of the folder in the "shared_folders" field
148 of the storage.
149
150 folders can be chained into a tree.
151
152 - parent is the parent of the folder.
153
154 - sibling_index is the index of the folder in the list of children
155 of the parent.
156
157 - children is the folder.
158*/
159
160struct mailfolder {
161 char * fld_pathname;
162 char * fld_virtual_name;
163
164 struct mailstorage * fld_storage;
165
166 mailsession * fld_session;
167 int fld_shared_session;
168 clistiter * fld_pos;
169
170 struct mailfolder * fld_parent;
171 unsigned int fld_sibling_index;
172 carray * fld_children; /* array of (struct mailfolder *) */
173
174 void * fld_user_data;
175};
176
177/*
178 this is the type of socket connection
179*/
180
181enum {
182 CONNECTION_TYPE_PLAIN, /* when the connection is plain text */
183 CONNECTION_TYPE_STARTTLS, /* when the connection is first plain,
184 then, we want to switch to
185 TLS (secure connection) */
186 CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain,
187 then, we will try to switch to TLS */
188 CONNECTION_TYPE_TLS, /* the connection is over TLS */
189 CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */
190 CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell
191 command and STARTTLS will be used */
192 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over
193 a shell command and STARTTLS will
194 be tried */
195 CONNECTION_TYPE_COMMAND_TLS, /* the connection is over a shell
196 command in TLS */
197};
198
199#ifdef __cplusplus
200}
201#endif
202
203#endif
diff --git a/libetpan/src/driver/tools/generic_cache.c b/libetpan/src/driver/tools/generic_cache.c
new file mode 100644
index 0000000..3ff6e43
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache.c
@@ -0,0 +1,729 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "generic_cache.h"
37
38#include "libetpan-config.h"
39
40#include <unistd.h>
41#include <string.h>
42#include <sys/mman.h>
43#include <stdio.h>
44#include <sys/types.h>
45#include <sys/stat.h>
46#include <fcntl.h>
47#include <unistd.h>
48#include <stdlib.h>
49
50#include "maildriver_types.h"
51#include "imfcache.h"
52#include "chash.h"
53#include "mailmessage.h"
54#include "mail_cache_db.h"
55
56int generic_cache_create_dir(char * dirname)
57{
58 struct stat buf;
59 int r;
60
61 r = stat(dirname, &buf);
62 if (r != 0) {
63 r = mkdir(dirname, 0700);
64
65 if (r < 0)
66 return MAIL_ERROR_FILE;
67 }
68 else {
69 if (!S_ISDIR(buf.st_mode))
70 return MAIL_ERROR_FILE;
71 }
72
73 return MAIL_NO_ERROR;
74}
75
76int generic_cache_store(char * filename, char * content, size_t length)
77{
78 int fd;
79 char * str;
80
81 fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
82 if (fd == -1)
83 return MAIL_ERROR_FILE;
84
85 if (ftruncate(fd, length) < 0)
86 return MAIL_ERROR_FILE;
87
88 str = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
89 if (str == MAP_FAILED)
90 return MAIL_ERROR_FILE;
91
92 memcpy(str, content, length);
93 msync(str, length, MS_SYNC);
94 munmap(str, length);
95
96 close(fd);
97
98 return MAIL_NO_ERROR;
99}
100
101int generic_cache_read(char * filename, char ** result, size_t * result_len)
102{
103 int fd;
104 char * str;
105 struct stat buf;
106 MMAPString * mmapstr;
107 char * content;
108 int res;
109
110 if (stat(filename, &buf) < 0) {
111 res = MAIL_ERROR_CACHE_MISS;
112 goto err;
113 }
114
115 fd = open(filename, O_RDONLY);
116 if (fd == -1) {
117 res = MAIL_ERROR_CACHE_MISS;
118 goto err;
119 }
120
121 str = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
122 if (str == MAP_FAILED) {
123 res = MAIL_ERROR_FILE;
124 goto close;
125 }
126
127 mmapstr = mmap_string_new_len(str, buf.st_size);
128 if (mmapstr == NULL) {
129 res = MAIL_ERROR_MEMORY;
130 goto unmap;
131 }
132
133 if (mmap_string_ref(mmapstr) < 0) {
134 res = MAIL_ERROR_MEMORY;
135 goto free;
136 }
137
138 content = mmapstr->str;
139
140 munmap(str, buf.st_size);
141 close(fd);
142
143 * result = content;
144 * result_len = buf.st_size;
145
146 return MAIL_NO_ERROR;
147
148 free:
149 mmap_string_free(mmapstr);
150 unmap:
151 munmap(str, buf.st_size);
152 close:
153 close(fd);
154 err:
155 return res;
156}
157
158static int flags_extension_read(MMAPString * mmapstr, size_t * index,
159 clist ** result)
160{
161 clist * list;
162 int r;
163 uint32_t count;
164 uint32_t i;
165 int res;
166
167 r = mailimf_cache_int_read(mmapstr, index, &count);
168 if (r != MAIL_NO_ERROR) {
169 res = r;
170 goto err;
171 }
172
173 list = clist_new();
174 if (list == NULL) {
175 res = MAIL_ERROR_MEMORY;
176 goto err;
177 }
178
179 for(i = 0 ; i < count ; i++) {
180 char * str;
181
182 r = mailimf_cache_string_read(mmapstr, index, &str);
183 if (r != MAIL_NO_ERROR) {
184 res = r;
185 goto free_list;
186 }
187
188 r = clist_append(list, str);
189 if (r < 0) {
190 free(str);
191 res = MAIL_ERROR_MEMORY;
192 goto free_list;
193 }
194 }
195
196 * result = list;
197
198 return MAIL_NO_ERROR;
199
200 free_list:
201 clist_foreach(list, (clist_func) free, NULL);
202 clist_free(list);
203 err:
204 return res;
205}
206
207static int generic_flags_read(MMAPString * mmapstr, size_t * index,
208 struct mail_flags ** result)
209{
210 clist * ext;
211 int r;
212 struct mail_flags * flags;
213 uint32_t value;
214 int res;
215
216 r = mailimf_cache_int_read(mmapstr, index, &value);
217 if (r != MAIL_NO_ERROR) {
218 res = r;
219 goto err;
220 }
221
222 r = flags_extension_read(mmapstr, index, &ext);
223 if (r != MAIL_NO_ERROR) {
224 res = r;
225 goto err;
226 }
227
228 flags = mail_flags_new(value, ext);
229 if (flags == NULL) {
230 res = r;
231 goto free;
232 }
233
234 * result = flags;
235
236 return MAIL_NO_ERROR;
237
238 free:
239 clist_foreach(ext, (clist_func) free, NULL);
240 clist_free(ext);
241 err:
242 return res;
243}
244
245static int flags_extension_write(MMAPString * mmapstr, size_t * index,
246 clist * ext)
247{
248 int r;
249 clistiter * cur;
250
251 r = mailimf_cache_int_write(mmapstr, index, clist_count(ext));
252 if (r != MAIL_NO_ERROR)
253 return r;
254
255 for(cur = clist_begin(ext) ; cur != NULL ; cur = clist_next(cur)) {
256 r = mailimf_cache_string_write(mmapstr, index,
257 clist_content(cur), strlen(clist_content(cur)));
258 if (r != MAIL_NO_ERROR)
259 return r;
260 }
261
262 return MAIL_NO_ERROR;
263}
264
265static int generic_flags_write(MMAPString * mmapstr, size_t * index,
266 struct mail_flags * flags)
267{
268 int r;
269
270 r = mailimf_cache_int_write(mmapstr, index,
271 flags->fl_flags & ~MAIL_FLAG_NEW);
272 if (r != MAIL_NO_ERROR)
273 return r;
274
275 r = flags_extension_write(mmapstr, index,
276 flags->fl_extension);
277 if (r != MAIL_NO_ERROR)
278 return r;
279
280 return MAIL_NO_ERROR;
281}
282
283
284
285
286static struct mail_flags * mail_flags_dup(struct mail_flags * flags)
287{
288 clist * list;
289 struct mail_flags * new_flags;
290 int r;
291 clistiter * cur;
292
293 list = clist_new();
294 if (list == NULL) {
295 goto err;
296 }
297
298 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
299 cur = clist_next(cur)) {
300 char * ext;
301
302 ext = strdup(clist_content(cur));
303 if (ext == NULL) {
304 goto free;
305 }
306
307 r = clist_append(list, ext);
308 if (r < 0) {
309 free(ext);
310 goto free;
311 }
312 }
313
314 new_flags = mail_flags_new(flags->fl_flags, list);
315 if (new_flags == NULL) {
316 goto free;
317 }
318
319 return new_flags;
320
321 free:
322 clist_foreach(list, (clist_func) free, NULL);
323 clist_free(list);
324 err:
325 return NULL;
326}
327
328static mailmessage * mailmessage_build(mailmessage * msg)
329{
330 mailmessage * new_msg;
331
332 new_msg = malloc(sizeof(* new_msg));
333 if (new_msg == NULL)
334 goto err;
335
336 new_msg->msg_session = msg->msg_session;
337 new_msg->msg_driver = msg->msg_driver;
338 new_msg->msg_index = msg->msg_index;
339 if (msg->msg_uid == NULL)
340 new_msg->msg_uid = NULL;
341 else {
342 new_msg->msg_uid = strdup(msg->msg_uid);
343 if (new_msg->msg_uid == NULL)
344 goto free;
345 }
346
347 new_msg->msg_cached = msg->msg_cached;
348 new_msg->msg_size = msg->msg_size;
349 new_msg->msg_fields = NULL;
350 new_msg->msg_flags = mail_flags_dup(msg->msg_flags);
351 if (new_msg->msg_flags == NULL) {
352 free(new_msg->msg_uid);
353 goto free;
354 }
355
356 new_msg->msg_mime = NULL;
357 new_msg->msg_data = NULL;
358
359 return new_msg;
360
361 free:
362 free(new_msg);
363 err:
364 return NULL;
365}
366
367struct mail_flags_store * mail_flags_store_new(void)
368{
369 struct mail_flags_store * flags_store;
370
371 flags_store = malloc(sizeof(struct mail_flags_store));
372 if (flags_store == NULL)
373 goto err;
374
375 flags_store->fls_tab = carray_new(128);
376 if (flags_store->fls_tab == NULL)
377 goto free;
378
379 flags_store->fls_hash = chash_new(128, CHASH_COPYALL);
380 if (flags_store->fls_hash == NULL)
381 goto free_tab;
382
383 return flags_store;
384
385 free_tab:
386 carray_free(flags_store->fls_tab);
387 free:
388 free(flags_store);
389 err:
390 return NULL;
391}
392
393void mail_flags_store_clear(struct mail_flags_store * flags_store)
394{
395 unsigned int i;
396
397 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
398 chashdatum key;
399 mailmessage * msg;
400
401 msg = carray_get(flags_store->fls_tab, i);
402
403 key.data = &msg->msg_index;
404 key.len = sizeof(msg->msg_index);
405 chash_delete(flags_store->fls_hash, &key, NULL);
406
407 mailmessage_free(msg);
408 }
409 carray_set_size(flags_store->fls_tab, 0);
410}
411
412void mail_flags_store_free(struct mail_flags_store * flags_store)
413{
414 mail_flags_store_clear(flags_store);
415 chash_free(flags_store->fls_hash);
416 carray_free(flags_store->fls_tab);
417 free(flags_store);
418}
419
420int mail_flags_store_set(struct mail_flags_store * flags_store,
421 mailmessage * msg)
422{
423 chashdatum key;
424 chashdatum value;
425 unsigned int index;
426 int res;
427 int r;
428 mailmessage * new_msg;
429
430 if (msg->msg_flags == NULL) {
431 res = MAIL_NO_ERROR;
432 goto err;
433 }
434
435 /* duplicate needed message info */
436 new_msg = mailmessage_build(msg);
437 if (new_msg == NULL) {
438 res = MAIL_ERROR_MEMORY;
439 goto err;
440 }
441
442 key.data = &new_msg->msg_index;
443 key.len = sizeof(new_msg->msg_index);
444
445 r = chash_get(flags_store->fls_hash, &key, &value);
446 if (r == 0) {
447 mailmessage * old_msg;
448
449 index = * (unsigned int *) value.data;
450 old_msg = carray_get(flags_store->fls_tab, index);
451 mailmessage_free(old_msg);
452 }
453 else {
454 r = carray_set_size(flags_store->fls_tab,
455 carray_count(flags_store->fls_tab) + 1);
456 if (r != 0) {
457 res = MAIL_ERROR_MEMORY;
458 goto err;
459 }
460 index = carray_count(flags_store->fls_tab) - 1;
461 }
462
463 carray_set(flags_store->fls_tab, index, new_msg);
464
465 value.data = &index;
466 value.len = sizeof(index);
467
468 r = chash_set(flags_store->fls_hash, &key, &value, NULL);
469 if (r < 0) {
470 carray_delete(flags_store->fls_tab, index);
471 res = MAIL_ERROR_MEMORY;
472 goto free;
473 }
474
475 return MAIL_NO_ERROR;
476
477 free:
478 mailmessage_free(new_msg);
479 err:
480 return res;
481}
482
483static int msg_index_compare(mailmessage ** msg1, mailmessage ** msg2)
484{
485 return (* msg1)->msg_index - (* msg2)->msg_index;
486}
487
488void mail_flags_store_sort(struct mail_flags_store * flags_store)
489{
490 qsort(carray_data(flags_store->fls_tab),
491 carray_count(flags_store->fls_tab), sizeof(mailmessage *),
492 (int (*)(const void *, const void *)) msg_index_compare);
493}
494
495struct mail_flags *
496mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index)
497{
498 struct mail_flags * flags;
499 chashdatum key;
500 chashdatum value;
501 int r;
502 unsigned int tab_index;
503 mailmessage * msg;
504
505 key.data = &index;
506 key.len = sizeof(index);
507
508 r = chash_get(flags_store->fls_hash, &key, &value);
509
510 if (r < 0)
511 return NULL;
512
513#if 0
514 flags = mail_flags_dup((struct mail_flags *) value.data);
515#endif
516 tab_index = * (unsigned int *) value.data;
517 msg = carray_get(flags_store->fls_tab, tab_index);
518 if (msg->msg_flags == NULL)
519 return NULL;
520
521 flags = mail_flags_dup(msg->msg_flags);
522
523 return flags;
524}
525
526int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2)
527{
528 clistiter * cur1;
529
530 if (clist_count(flags1->fl_extension) != clist_count(flags2->fl_extension))
531 return -1;
532
533 for(cur1 = clist_begin(flags1->fl_extension) ; cur1 != NULL ;
534 cur1 = clist_next(cur1)) {
535 char * flag1;
536 clistiter * cur2;
537 int found;
538
539 flag1 = clist_content(cur1);
540
541 found = 0;
542 for(cur2 = clist_begin(flags2->fl_extension) ; cur2 != NULL ;
543 cur2 = clist_next(cur2)) {
544 char * flag2;
545
546 flag2 = clist_content(cur2);
547
548 if (strcasecmp(flag1, flag2) == 0) {
549 found = 1;
550 break;
551 }
552 }
553
554 if (!found)
555 return -1;
556 }
557
558 return flags1->fl_flags - flags2->fl_flags;
559}
560
561
562int generic_cache_fields_read(struct mail_cache_db * cache_db,
563 MMAPString * mmapstr,
564 char * keyname, struct mailimf_fields ** result)
565{
566 int r;
567 int res;
568 size_t cur_token;
569 struct mailimf_fields * fields;
570 void * data;
571 size_t data_len;
572
573 r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len);
574 if (r != 0) {
575 res = MAIL_ERROR_CACHE_MISS;
576 goto err;
577 }
578
579 r = mail_serialize_clear(mmapstr, &cur_token);
580 if (r != MAIL_NO_ERROR) {
581 res = r;
582 goto err;
583 }
584
585 if (mmap_string_append_len(mmapstr, data, data_len) == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto err;
588 }
589
590 r = mailimf_cache_fields_read(mmapstr, &cur_token, &fields);
591 if (r != MAIL_NO_ERROR) {
592 res = r;
593 goto err;
594 }
595
596 * result = fields;
597
598 return MAIL_NO_ERROR;
599
600 err:
601 return res;
602}
603
604int generic_cache_fields_write(struct mail_cache_db * cache_db,
605 MMAPString * mmapstr,
606 char * keyname, struct mailimf_fields * fields)
607{
608 int r;
609 int res;
610 size_t cur_token;
611
612 r = mail_serialize_clear(mmapstr, &cur_token);
613 if (r != MAIL_NO_ERROR) {
614 res = r;
615 goto err;
616 }
617
618 r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
619 if (r != MAIL_NO_ERROR) {
620 res = r;
621 goto err;
622 }
623
624 r = mail_cache_db_put(cache_db, keyname, strlen(keyname),
625 mmapstr->str, mmapstr->len);
626 if (r != 0) {
627 res = MAIL_ERROR_FILE;
628 goto err;
629 }
630
631 return MAIL_NO_ERROR;
632
633 err:
634 return res;
635}
636
637int generic_cache_flags_read(struct mail_cache_db * cache_db,
638 MMAPString * mmapstr,
639 char * keyname, struct mail_flags ** result)
640{
641 int r;
642 int res;
643 size_t cur_token;
644 struct mail_flags * flags;
645 void * data;
646 size_t data_len;
647
648 r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len);
649 if (r != 0) {
650 res = MAIL_ERROR_CACHE_MISS;
651 goto err;
652 }
653
654 r = mail_serialize_clear(mmapstr, &cur_token);
655 if (r != MAIL_NO_ERROR) {
656 res = r;
657 goto err;
658 }
659
660 if (mmap_string_append_len(mmapstr, data, data_len) == NULL) {
661 res = MAIL_ERROR_MEMORY;
662 goto err;
663 }
664
665 r = generic_flags_read(mmapstr, &cur_token, &flags);
666 if (r != MAIL_NO_ERROR) {
667 res = r;
668 goto err;
669 }
670
671 * result = flags;
672
673 return MAIL_NO_ERROR;
674
675 err:
676 return res;
677}
678
679int generic_cache_flags_write(struct mail_cache_db * cache_db,
680 MMAPString * mmapstr,
681 char * keyname, struct mail_flags * flags)
682{
683 int r;
684 int res;
685 size_t cur_token;
686
687 r = mail_serialize_clear(mmapstr, &cur_token);
688 if (r != MAIL_NO_ERROR) {
689 res = r;
690 goto err;
691 }
692
693 r = generic_flags_write(mmapstr, &cur_token, flags);
694 if (r != MAIL_NO_ERROR) {
695 res = r;
696 goto err;
697 }
698
699 r = mail_cache_db_put(cache_db, keyname, strlen(keyname),
700 mmapstr->str, mmapstr->len);
701 if (r != 0) {
702 res = MAIL_ERROR_FILE;
703 goto err;
704 }
705
706 return MAIL_NO_ERROR;
707
708 err:
709 return res;
710}
711
712
713int generic_cache_delete(struct mail_cache_db * cache_db,
714 char * keyname)
715{
716 int r;
717 int res;
718
719 r = mail_cache_db_del(cache_db, keyname, strlen(keyname));
720 if (r != 0) {
721 res = MAIL_ERROR_FILE;
722 goto err;
723 }
724
725 return MAIL_NO_ERROR;
726
727 err:
728 return res;
729}
diff --git a/libetpan/src/driver/tools/generic_cache.h b/libetpan/src/driver/tools/generic_cache.h
new file mode 100644
index 0000000..934a53d
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache.h
@@ -0,0 +1,109 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef GENERIC_CACHE_H
37
38#define GENERIC_CACHE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "generic_cache_types.h"
45#include "mailmessage_types.h"
46#include "chash.h"
47#include "carray.h"
48#include "mail_cache_db_types.h"
49
50int generic_cache_create_dir(char * dirname);
51
52int generic_cache_store(char * filename, char * content, size_t length);
53int generic_cache_read(char * filename, char ** result, size_t * result_len);
54
55int generic_cache_fields_read(struct mail_cache_db * cache_db,
56 MMAPString * mmapstr,
57 char * keyname, struct mailimf_fields ** result);
58
59int generic_cache_fields_write(struct mail_cache_db * cache_db,
60 MMAPString * mmapstr,
61 char * keyname, struct mailimf_fields * fields);
62
63int generic_cache_flags_read(struct mail_cache_db * cache_db,
64 MMAPString * mmapstr,
65 char * keyname, struct mail_flags ** result);
66
67int generic_cache_flags_write(struct mail_cache_db * cache_db,
68 MMAPString * mmapstr,
69 char * keyname, struct mail_flags * flags);
70
71int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname);
72
73#if 0
74int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr,
75 char * keyname, struct mailimf_fields ** result);
76
77int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr,
78 char * keyname, struct mailimf_fields * fields);
79
80int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr,
81 char * keyname, struct mail_flags ** result);
82
83int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr,
84 char * keyname, struct mail_flags * flags);
85
86int generic_cache_delete(DB * dbp, char * keyname);
87#endif
88
89struct mail_flags_store * mail_flags_store_new(void);
90
91void mail_flags_store_clear(struct mail_flags_store * flags_store);
92
93void mail_flags_store_free(struct mail_flags_store * flags_store);
94
95int mail_flags_store_set(struct mail_flags_store * flags_store,
96 mailmessage * msg);
97
98void mail_flags_store_sort(struct mail_flags_store * flags_store);
99
100struct mail_flags *
101mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index);
102
103int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2);
104
105#ifdef __cplusplus
106}
107#endif
108
109#endif
diff --git a/libetpan/src/driver/tools/generic_cache_types.h b/libetpan/src/driver/tools/generic_cache_types.h
new file mode 100644
index 0000000..bc69b3c
--- a/dev/null
+++ b/libetpan/src/driver/tools/generic_cache_types.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef GENERIC_CACHE_TYPE_H
37
38#define GENERIC_CACHE_TYPE_H
39
40#include <libetpan/carray.h>
41#include <libetpan/chash.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47struct mail_flags_store {
48 carray * fls_tab;
49 chash * fls_hash;
50};
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/driver/tools/imfcache.c b/libetpan/src/driver/tools/imfcache.c
new file mode 100644
index 0000000..7c6a5be
--- a/dev/null
+++ b/libetpan/src/driver/tools/imfcache.c
@@ -0,0 +1,1429 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imfcache.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index,
42 struct mailimf_field * field);
43static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index,
44 struct mailimf_orig_date * date);
45static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index,
46 struct mailimf_date_time * date_time);
47static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index,
48 struct mailimf_from * from);
49static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index,
50 struct mailimf_sender * sender);
51static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index,
52 struct mailimf_reply_to * reply_to);
53static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index,
54 struct mailimf_to * to);
55static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index,
56 struct mailimf_cc * to);
57static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index,
58 struct mailimf_bcc * to);
59static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index,
60 struct mailimf_message_id * message_id);
61static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index,
62 clist * list);
63static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index,
64 struct mailimf_in_reply_to *
65 in_reply_to);
66static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index,
67 struct mailimf_references * references);
68static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index,
69 struct mailimf_subject * subject);
70static int mailimf_cache_address_list_write(MMAPString * mmapstr,
71 size_t * index,
72 struct mailimf_address_list *
73 addr_list);
74static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index,
75 struct mailimf_address * addr);
76static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index,
77 struct mailimf_group * group);
78static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr,
79 size_t * index,
80 struct mailimf_mailbox_list * mb_list);
81static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index,
82 struct mailimf_mailbox * mb);
83
84
85static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index,
86 struct mailimf_field ** result);
87static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index,
88 struct mailimf_orig_date ** result);
89static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index,
90 struct mailimf_date_time ** result);
91static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index,
92 struct mailimf_from ** result);
93static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index,
94 struct mailimf_sender ** result);
95static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index,
96 struct mailimf_reply_to ** result);
97static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index,
98 struct mailimf_to ** result);
99static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index,
100 struct mailimf_cc ** result);
101static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index,
102 struct mailimf_bcc ** result);
103static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index,
104 struct mailimf_message_id ** result);
105static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index,
106 clist ** result);
107static int
108mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index,
109 struct mailimf_in_reply_to ** result);
110
111static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index,
112 struct mailimf_references ** result);
113static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index,
114 struct mailimf_subject ** result);
115static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index,
116 struct mailimf_address_list ** result);
117static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index,
118 struct mailimf_address ** result);
119static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index,
120 struct mailimf_group ** result);
121static int
122mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index,
123 struct mailimf_mailbox_list ** result);
124static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index,
125 struct mailimf_mailbox ** result);
126
127enum {
128 CACHE_NULL_POINTER = 0,
129 CACHE_NOT_NULL = 1,
130};
131
132int mail_serialize_clear(MMAPString * mmapstr, size_t * index)
133{
134 if (mmap_string_set_size(mmapstr, 0) == NULL)
135 return MAIL_ERROR_MEMORY;
136
137 * index = 0;
138
139 return MAIL_NO_ERROR;
140}
141
142int mail_serialize_write(MMAPString * mmapstr, size_t * index,
143 char * buf, size_t size)
144{
145 if (mmap_string_append_len(mmapstr, buf, size) == NULL)
146 return MAIL_ERROR_MEMORY;
147
148 * index = * index + size;
149
150 return MAIL_NO_ERROR;
151}
152
153int mail_serialize_read(MMAPString * mmapstr, size_t * index,
154 char * buf, size_t size)
155{
156 size_t cur_token;
157
158 cur_token = * index;
159
160 if (cur_token + size > mmapstr->len)
161 return MAIL_ERROR_STREAM;
162
163 memcpy(buf, mmapstr->str + cur_token, size);
164 * index = cur_token + size;
165
166 return MAIL_NO_ERROR;
167}
168
169int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index,
170 uint32_t value)
171{
172 unsigned char ch;
173 int r;
174 int i;
175
176 for(i = 0 ; i < 4 ; i ++) {
177 ch = value % 256;
178
179 r = mail_serialize_write(mmapstr, index, &ch, 1);
180 if (r != MAIL_NO_ERROR)
181 return r;
182 value /= 256;
183 }
184
185 return MAIL_NO_ERROR;
186}
187
188int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index,
189 uint32_t * result)
190{
191 unsigned char ch;
192 uint32_t value;
193 int i;
194 int r;
195
196 value = 0;
197 for(i = 0 ; i < 4 ; i ++) {
198 r = mail_serialize_read(mmapstr, index, &ch, 1);
199 if (r != MAIL_NO_ERROR)
200 return r;
201 value = value | ch << (i << 3);
202 }
203
204 * result = value;
205
206 return MAIL_NO_ERROR;
207}
208
209
210int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index,
211 char * str, size_t length)
212{
213 int r;
214
215 if (str == NULL) {
216 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
217 if (r != MAIL_NO_ERROR)
218 return r;
219 }
220 else {
221 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
222 if (r != MAIL_NO_ERROR)
223 return r;
224
225 r = mailimf_cache_int_write(mmapstr, index, length);
226 if (r != MAIL_NO_ERROR)
227 return r;
228
229 if (length != 0) {
230 r = mail_serialize_write(mmapstr, index, str, length);
231 if (r != MAIL_NO_ERROR)
232 return MAIL_ERROR_FILE;
233 }
234 }
235
236 return MAIL_NO_ERROR;
237}
238
239int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index,
240 char ** result)
241{
242 int r;
243 uint32_t length;
244 char * str;
245 uint32_t type;
246
247 r = mailimf_cache_int_read(mmapstr, index, &type);
248 if (r != MAIL_NO_ERROR)
249 return r;
250
251 if (type == CACHE_NULL_POINTER) {
252 str = NULL;
253 }
254 else {
255 r = mailimf_cache_int_read(mmapstr, index, &length);
256 if (r != MAIL_NO_ERROR)
257 return r;
258
259 str = malloc(length + 1);
260 if (str == NULL)
261 return MAIL_ERROR_MEMORY;
262
263 r = mail_serialize_read(mmapstr, index, str, length);
264 if (r != MAIL_NO_ERROR)
265 return MAIL_ERROR_FILE;
266
267 str[length] = 0;
268 }
269
270 * result = str;
271
272 return MAIL_NO_ERROR;
273}
274
275int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index,
276 struct mailimf_fields * fields)
277{
278 clistiter * cur;
279 int r;
280
281 r = mailimf_cache_int_write(mmapstr, index,
282 clist_count(fields->fld_list));
283 if (r != MAIL_NO_ERROR)
284 return r;
285
286 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
287 cur = clist_next(cur)) {
288 r = mailimf_cache_field_write(mmapstr, index, clist_content(cur));
289 if (r != MAIL_NO_ERROR)
290 return r;
291 }
292
293 return MAIL_NO_ERROR;
294}
295
296int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index,
297 struct mailimf_fields ** result)
298{
299 clist * list;
300 int r;
301 uint32_t count;
302 uint32_t i;
303 struct mailimf_fields * fields;
304 int res;
305
306 r = mailimf_cache_int_read(mmapstr, index, &count);
307 if (r != MAIL_NO_ERROR) {
308 res = r;
309 goto err;
310 }
311
312 list = clist_new();
313 if (list == NULL) {
314 res = MAIL_ERROR_MEMORY;
315 goto err;
316 }
317
318 for(i = 0 ; i < count ; i++) {
319 struct mailimf_field * field;
320
321 r = mailimf_cache_field_read(mmapstr, index, &field);
322 if (r != MAIL_NO_ERROR) {
323 res = r;
324 goto free_list;
325 }
326
327 r = clist_append(list, field);
328 if (r < 0) {
329 mailimf_field_free(field);
330 res = MAIL_ERROR_MEMORY;
331 goto free_list;
332 }
333 }
334
335 fields = mailimf_fields_new(list);
336 if (fields == NULL) {
337 res = MAIL_ERROR_MEMORY;
338 goto free_list;
339 }
340
341 * result = fields;
342
343 return MAIL_NO_ERROR;
344
345 free_list:
346 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
347 clist_free(list);
348 err:
349 return res;
350}
351
352
353static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index,
354 struct mailimf_field * field)
355{
356 int r;
357
358 r = mailimf_cache_int_write(mmapstr, index, field->fld_type);
359 if (r != MAIL_NO_ERROR)
360 return r;
361
362 switch (field->fld_type) {
363 case MAILIMF_FIELD_ORIG_DATE:
364 r = mailimf_cache_orig_date_write(mmapstr, index,
365 field->fld_data.fld_orig_date);
366 break;
367 case MAILIMF_FIELD_FROM:
368 r = mailimf_cache_from_write(mmapstr, index,
369 field->fld_data.fld_from);
370 break;
371 case MAILIMF_FIELD_SENDER:
372 r = mailimf_cache_sender_write(mmapstr, index,
373 field->fld_data.fld_sender);
374 break;
375 case MAILIMF_FIELD_REPLY_TO:
376 r = mailimf_cache_reply_to_write(mmapstr, index,
377 field->fld_data.fld_reply_to);
378 break;
379 case MAILIMF_FIELD_TO:
380 r = mailimf_cache_to_write(mmapstr, index,
381 field->fld_data.fld_to);
382 break;
383 case MAILIMF_FIELD_CC:
384 r = mailimf_cache_cc_write(mmapstr, index,
385 field->fld_data.fld_cc);
386 break;
387 case MAILIMF_FIELD_BCC:
388 r = mailimf_cache_bcc_write(mmapstr, index,
389 field->fld_data.fld_bcc);
390 break;
391 case MAILIMF_FIELD_MESSAGE_ID:
392 r = mailimf_cache_message_id_write(mmapstr, index,
393 field->fld_data.fld_message_id);
394 break;
395 case MAILIMF_FIELD_IN_REPLY_TO:
396 r = mailimf_cache_in_reply_to_write(mmapstr, index,
397 field->fld_data.fld_in_reply_to);
398 break;
399 case MAILIMF_FIELD_REFERENCES:
400 r = mailimf_cache_references_write(mmapstr, index,
401 field->fld_data.fld_references);
402 break;
403 case MAILIMF_FIELD_SUBJECT:
404 r = mailimf_cache_subject_write(mmapstr, index,
405 field->fld_data.fld_subject);
406 break;
407 default:
408 r = 0;
409 break;
410 }
411
412 if (r != MAIL_NO_ERROR)
413 return r;
414
415 return MAIL_NO_ERROR;
416}
417
418
419static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index,
420 struct mailimf_field ** result)
421{
422 int r;
423 uint32_t type;
424 struct mailimf_orig_date * orig_date;
425 struct mailimf_from * from;
426 struct mailimf_sender * sender;
427 struct mailimf_to * to;
428 struct mailimf_reply_to * reply_to;
429 struct mailimf_cc * cc;
430 struct mailimf_bcc * bcc;
431 struct mailimf_message_id * message_id;
432 struct mailimf_in_reply_to * in_reply_to;
433 struct mailimf_references * references;
434 struct mailimf_subject * subject;
435 struct mailimf_field * field;
436 int res;
437
438 orig_date = NULL;
439 from = NULL;
440 sender = NULL;
441 to = NULL;
442 reply_to = NULL;
443 cc = NULL;
444 bcc = NULL;
445 message_id = NULL;
446 in_reply_to = NULL;
447 references = NULL;
448 subject = NULL;
449 field = NULL;
450
451 r = mailimf_cache_int_read(mmapstr, index, &type);
452 if (r != MAIL_NO_ERROR) {
453 res = r;
454 goto err;
455 }
456
457 switch (type) {
458 case MAILIMF_FIELD_ORIG_DATE:
459 r = mailimf_cache_orig_date_read(mmapstr, index, &orig_date);
460 break;
461 case MAILIMF_FIELD_FROM:
462 r = mailimf_cache_from_read(mmapstr, index, &from);
463 break;
464 case MAILIMF_FIELD_SENDER:
465 r = mailimf_cache_sender_read(mmapstr, index, &sender);
466 break;
467 case MAILIMF_FIELD_REPLY_TO:
468 r = mailimf_cache_reply_to_read(mmapstr, index, &reply_to);
469 break;
470 case MAILIMF_FIELD_TO:
471 r = mailimf_cache_to_read(mmapstr, index, &to);
472 break;
473 case MAILIMF_FIELD_CC:
474 r = mailimf_cache_cc_read(mmapstr, index, &cc);
475 break;
476 case MAILIMF_FIELD_BCC:
477 r = mailimf_cache_bcc_read(mmapstr, index, &bcc);
478 break;
479 case MAILIMF_FIELD_MESSAGE_ID:
480 r = mailimf_cache_message_id_read(mmapstr, index, &message_id);
481 break;
482 case MAILIMF_FIELD_IN_REPLY_TO:
483 r = mailimf_cache_in_reply_to_read(mmapstr, index, &in_reply_to);
484 break;
485 case MAILIMF_FIELD_REFERENCES:
486 r = mailimf_cache_references_read(mmapstr, index, &references);
487 break;
488 case MAILIMF_FIELD_SUBJECT:
489 r = mailimf_cache_subject_read(mmapstr, index, &subject);
490 break;
491 default:
492 r = MAIL_ERROR_INVAL;
493 break;
494 }
495
496 if (r != MAIL_NO_ERROR) {
497 res = r;
498 goto free;
499 }
500
501 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
502 NULL, NULL, NULL, orig_date, from, sender, reply_to,
503 to, cc, bcc, message_id,
504 in_reply_to, references,
505 subject, NULL, NULL, NULL);
506 if (field == NULL) {
507 res = MAIL_ERROR_MEMORY;
508 goto free;
509 }
510
511 * result = field;
512
513 return MAIL_NO_ERROR;
514
515 free:
516 if (orig_date != NULL)
517 mailimf_orig_date_free(orig_date);
518 if (from != NULL)
519 mailimf_from_free(from);
520 if (sender != NULL)
521 mailimf_sender_free(sender);
522 if (reply_to != NULL)
523 mailimf_reply_to_free(reply_to);
524 if (to != NULL)
525 mailimf_to_free(to);
526 if (cc != NULL)
527 mailimf_cc_free(cc);
528 if (bcc != NULL)
529 mailimf_bcc_free(bcc);
530 if (message_id != NULL)
531 mailimf_message_id_free(message_id);
532 if (in_reply_to != NULL)
533 mailimf_in_reply_to_free(in_reply_to);
534 if (references != NULL)
535 mailimf_references_free(references);
536 if (subject != NULL)
537 mailimf_subject_free(subject);
538 err:
539 return res;
540}
541
542static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index,
543 struct mailimf_orig_date * date)
544{
545 return mailimf_cache_date_time_write(mmapstr, index, date->dt_date_time);
546}
547
548static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index,
549 struct mailimf_orig_date ** result)
550{
551 int r;
552 struct mailimf_date_time * date_time;
553 struct mailimf_orig_date * orig_date;
554
555 r = mailimf_cache_date_time_read(mmapstr, index, &date_time);
556 if (r != MAIL_NO_ERROR)
557 return r;
558
559 orig_date = mailimf_orig_date_new(date_time);
560 if (orig_date == NULL) {
561 mailimf_date_time_free(date_time);
562 return MAIL_ERROR_MEMORY;
563 }
564
565 * result = orig_date;
566
567 return MAIL_NO_ERROR;
568}
569
570static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index,
571 struct mailimf_date_time * date_time)
572{
573 int r;
574
575 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_day);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_month);
580 if (r != MAIL_NO_ERROR)
581 return r;
582
583 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_year);
584 if (r != MAIL_NO_ERROR)
585 return r;
586
587 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_hour);
588 if (r != MAIL_NO_ERROR)
589 return r;
590
591 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_min);
592 if (r != MAIL_NO_ERROR)
593 return r;
594
595 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_sec);
596 if (r != MAIL_NO_ERROR)
597 return r;
598
599 r = mailimf_cache_int_write(mmapstr, index, date_time->dt_zone);
600 if (r != MAIL_NO_ERROR)
601 return r;
602
603 return MAIL_NO_ERROR;
604}
605
606static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index,
607 struct mailimf_date_time ** result)
608{
609 int r;
610 uint32_t day;
611 uint32_t month;
612 uint32_t year;
613 uint32_t hour;
614 uint32_t min;
615 uint32_t sec;
616 uint32_t zone;
617 struct mailimf_date_time * date_time;
618
619 r = mailimf_cache_int_read(mmapstr, index, &day);
620 if (r != MAIL_NO_ERROR)
621 return r;
622
623 r = mailimf_cache_int_read(mmapstr, index, &month);
624 if (r != MAIL_NO_ERROR)
625 return r;
626
627 r = mailimf_cache_int_read(mmapstr, index, &year);
628 if (r != MAIL_NO_ERROR)
629 return r;
630
631 r = mailimf_cache_int_read(mmapstr, index, &hour);
632 if (r != MAIL_NO_ERROR)
633 return r;
634
635 r = mailimf_cache_int_read(mmapstr, index, &min);
636 if (r != MAIL_NO_ERROR)
637 return r;
638
639 r = mailimf_cache_int_read(mmapstr, index, &sec);
640 if (r != MAIL_NO_ERROR)
641 return r;
642
643 r = mailimf_cache_int_read(mmapstr, index, &zone);
644 if (r != MAIL_NO_ERROR)
645 return r;
646
647 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
648 if (date_time == NULL)
649 return MAIL_ERROR_MEMORY;
650
651 * result = date_time;
652
653 return MAIL_NO_ERROR;
654
655}
656
657
658static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index,
659 struct mailimf_from * from)
660{
661 return mailimf_cache_mailbox_list_write(mmapstr, index, from->frm_mb_list);
662}
663
664static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index,
665 struct mailimf_from ** result)
666{
667 struct mailimf_mailbox_list * mb_list;
668 struct mailimf_from * from;
669 int r;
670
671 r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list);
672 if (r != MAIL_NO_ERROR)
673 return r;
674
675 from = mailimf_from_new(mb_list);
676 if (from == NULL) {
677 mailimf_mailbox_list_free(mb_list);
678 return MAIL_ERROR_MEMORY;
679 }
680
681 * result = from;
682
683 return MAIL_NO_ERROR;
684}
685
686static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index,
687 struct mailimf_sender * sender)
688{
689 return mailimf_cache_mailbox_write(mmapstr, index, sender->snd_mb);
690}
691
692static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index,
693 struct mailimf_sender ** result)
694{
695 int r;
696 struct mailimf_mailbox * mb;
697 struct mailimf_sender * sender;
698
699 r = mailimf_cache_mailbox_read(mmapstr, index, &mb);
700 if (r != MAIL_NO_ERROR)
701 return r;
702
703 sender = mailimf_sender_new(mb);
704 if (sender == NULL) {
705 mailimf_mailbox_free(mb);
706 return MAIL_ERROR_MEMORY;
707 }
708
709 * result = sender;
710
711 return MAIL_NO_ERROR;
712}
713
714static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index,
715 struct mailimf_reply_to * reply_to)
716{
717 return mailimf_cache_address_list_write(mmapstr, index,
718 reply_to->rt_addr_list);
719}
720
721static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index,
722 struct mailimf_reply_to ** result)
723{
724 int r;
725 struct mailimf_address_list * addr_list;
726 struct mailimf_reply_to * reply_to;
727
728 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
729 if (r != MAIL_NO_ERROR)
730 return r;
731
732 reply_to = mailimf_reply_to_new(addr_list);
733 if (reply_to == NULL) {
734 mailimf_address_list_free(addr_list);
735 return MAIL_ERROR_MEMORY;
736 }
737
738 * result = reply_to;
739
740 return MAIL_NO_ERROR;
741}
742
743static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index,
744 struct mailimf_to * to)
745{
746 return mailimf_cache_address_list_write(mmapstr, index, to->to_addr_list);
747}
748
749static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index,
750 struct mailimf_to ** result)
751{
752 int r;
753 struct mailimf_address_list * addr_list;
754 struct mailimf_to * to;
755
756 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
757 if (r != MAIL_NO_ERROR)
758 return r;
759
760 to = mailimf_to_new(addr_list);
761 if (to == NULL) {
762 mailimf_address_list_free(addr_list);
763 return MAIL_ERROR_MEMORY;
764 }
765
766 * result = to;
767
768 return MAIL_NO_ERROR;
769}
770
771static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index,
772 struct mailimf_cc * cc)
773{
774 return mailimf_cache_address_list_write(mmapstr, index, cc->cc_addr_list);
775}
776
777static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index,
778 struct mailimf_cc ** result)
779{
780 int r;
781 struct mailimf_address_list * addr_list;
782 struct mailimf_cc * cc;
783
784 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
785 if (r != MAIL_NO_ERROR)
786 return r;
787
788 cc = mailimf_cc_new(addr_list);
789 if (cc == NULL) {
790 mailimf_address_list_free(addr_list);
791 return MAIL_ERROR_MEMORY;
792 }
793
794 * result = cc;
795
796 return MAIL_NO_ERROR;
797}
798
799static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index,
800 struct mailimf_bcc * bcc)
801{
802 return mailimf_cache_address_list_write(mmapstr, index, bcc->bcc_addr_list);
803}
804
805static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index,
806 struct mailimf_bcc ** result)
807{
808 int r;
809 struct mailimf_address_list * addr_list;
810 struct mailimf_bcc * bcc;
811
812 r = mailimf_cache_address_list_read(mmapstr, index, &addr_list);
813 if (r != MAIL_NO_ERROR)
814 return r;
815
816 bcc = mailimf_bcc_new(addr_list);
817 if (bcc == NULL) {
818 mailimf_address_list_free(addr_list);
819 return MAIL_ERROR_MEMORY;
820 }
821
822 * result = bcc;
823
824 return MAIL_NO_ERROR;
825}
826
827static int
828mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index,
829 struct mailimf_message_id * message_id)
830{
831 return mailimf_cache_string_write(mmapstr, index,
832 message_id->mid_value, strlen(message_id->mid_value));
833}
834
835static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index,
836 struct mailimf_message_id ** result)
837{
838 struct mailimf_message_id * message_id;
839 char * str;
840 int r;
841
842 r = mailimf_cache_string_read(mmapstr, index, &str);
843 if (r != MAIL_NO_ERROR)
844 return r;
845
846 message_id = mailimf_message_id_new(str);
847 if (message_id == NULL) {
848 free(str);
849 return MAIL_ERROR_MEMORY;
850 }
851
852 * result = message_id;
853
854 return MAIL_NO_ERROR;
855}
856
857static int
858mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index,
859 clist * list)
860{
861 clistiter * cur;
862 int r;
863
864 r = mailimf_cache_int_write(mmapstr, index, clist_count(list));
865 if (r != MAIL_NO_ERROR)
866 return r;
867
868 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
869 char * msgid;
870
871 msgid = clist_content(cur);
872
873 r = mailimf_cache_string_write(mmapstr, index, msgid, strlen(msgid));
874 if (r != MAIL_NO_ERROR)
875 return r;
876 }
877
878 return MAIL_NO_ERROR;
879}
880
881static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index,
882 clist ** result)
883{
884 clist * list;
885 int r;
886 uint32_t count;
887 uint32_t i;
888 int res;
889
890 r = mailimf_cache_int_read(mmapstr, index, &count);
891 if (r != MAIL_NO_ERROR) {
892 res = r;
893 goto err;
894 }
895
896 list = clist_new();
897 if (list == NULL) {
898 res = MAIL_ERROR_MEMORY;
899 goto err;
900 }
901
902 for(i = 0 ; i < count ; i++) {
903 char * msgid;
904
905 r = mailimf_cache_string_read(mmapstr, index, &msgid);
906 if (r != MAIL_NO_ERROR) {
907 res = r;
908 goto err;
909 }
910
911 r = clist_append(list, msgid);
912 if (r < 0) {
913 free(msgid);
914 res = MAIL_ERROR_MEMORY;
915 goto free_list;
916 }
917 }
918
919 * result = list;
920
921 return MAIL_NO_ERROR;
922
923 free_list:
924 clist_foreach(list, (clist_func) free, NULL);
925 clist_free(list);
926 err:
927 return res;
928}
929
930static int
931mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index,
932 struct mailimf_in_reply_to * in_reply_to)
933{
934 return mailimf_cache_msg_id_list_write(mmapstr, index,
935 in_reply_to->mid_list);
936}
937
938static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index,
939 struct mailimf_in_reply_to ** result)
940{
941 int r;
942 clist * msg_id_list;
943 struct mailimf_in_reply_to * in_reply_to;
944
945 r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list);
946 if (r != MAIL_NO_ERROR)
947 return r;
948
949 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
950 if (in_reply_to == NULL) {
951 clist_foreach(msg_id_list, (clist_func) free, NULL);
952 clist_free(msg_id_list);
953 return MAIL_ERROR_MEMORY;
954 }
955
956 * result = in_reply_to;
957
958 return MAIL_NO_ERROR;
959}
960
961static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index,
962 struct mailimf_references * references)
963{
964 return mailimf_cache_msg_id_list_write(mmapstr, index,
965 references->mid_list);
966}
967
968static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index,
969 struct mailimf_references ** result)
970{
971 int r;
972 clist * msg_id_list;
973 struct mailimf_references * references;
974
975 r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list);
976 if (r != MAIL_NO_ERROR)
977 return r;
978
979 references = mailimf_references_new(msg_id_list);
980 if (references == NULL) {
981 clist_foreach(msg_id_list, (clist_func) free, NULL);
982 clist_free(msg_id_list);
983 return MAIL_ERROR_MEMORY;
984 }
985
986 * result = references;
987
988 return MAIL_NO_ERROR;
989}
990
991
992static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index,
993 struct mailimf_subject * subject)
994{
995 return mailimf_cache_string_write(mmapstr, index,
996 subject->sbj_value, strlen(subject->sbj_value));
997}
998
999static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index,
1000 struct mailimf_subject ** result)
1001{
1002 char * str;
1003 struct mailimf_subject * subject;
1004 int r;
1005
1006 r = mailimf_cache_string_read(mmapstr, index, &str);
1007 if (r != MAIL_NO_ERROR)
1008 return r;
1009
1010 if (str == NULL) {
1011 str = strdup("");
1012 if (str == NULL)
1013 return MAIL_ERROR_MEMORY;
1014 }
1015
1016 subject = mailimf_subject_new(str);
1017 if (subject == NULL) {
1018 free(str);
1019 return MAIL_ERROR_MEMORY;
1020 }
1021
1022 * result = subject;
1023
1024 return MAIL_NO_ERROR;
1025}
1026
1027
1028static int
1029mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * index,
1030 struct mailimf_address_list * addr_list)
1031{
1032 clistiter * cur;
1033 int r;
1034
1035 if (addr_list == NULL) {
1036 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
1037 if (r != MAIL_NO_ERROR)
1038 return r;
1039 }
1040 else {
1041 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
1042 if (r != MAIL_NO_ERROR)
1043 return r;
1044
1045 r = mailimf_cache_int_write(mmapstr, index,
1046 clist_count(addr_list->ad_list));
1047 if (r != MAIL_NO_ERROR)
1048 return r;
1049
1050 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1051 cur = clist_next(cur)) {
1052 struct mailimf_address * addr;
1053
1054 addr = clist_content(cur);
1055
1056 r = mailimf_cache_address_write(mmapstr, index, addr);
1057 if (r != MAIL_NO_ERROR)
1058 return r;
1059 }
1060 }
1061
1062 return MAIL_NO_ERROR;
1063}
1064
1065static int
1066mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index,
1067 struct mailimf_address_list ** result)
1068{
1069 struct mailimf_address_list * addr_list;
1070 uint32_t count;
1071 uint32_t i;
1072 int r;
1073 clist * list;
1074 int res;
1075 uint32_t type;
1076
1077 r = mailimf_cache_int_read(mmapstr, index, &type);
1078 if (r != MAIL_NO_ERROR) {
1079 res = r;
1080 goto err;
1081 }
1082
1083 if (type == CACHE_NULL_POINTER) {
1084 * result = NULL;
1085 return MAIL_NO_ERROR;
1086 }
1087
1088 r = mailimf_cache_int_read(mmapstr, index, &count);
1089 if (r != MAIL_NO_ERROR) {
1090 res = r;
1091 goto err;
1092 }
1093
1094 list = clist_new();
1095 if (list == NULL) {
1096 res = MAIL_ERROR_MEMORY;
1097 goto err;
1098 }
1099
1100 for(i = 0 ; i < count ; i++) {
1101 struct mailimf_address * addr;
1102
1103 r = mailimf_cache_address_read(mmapstr, index, &addr);
1104 if (r != MAIL_NO_ERROR) {
1105 res = r;
1106 goto free_list;
1107 }
1108
1109 r = clist_append(list, addr);
1110 if (r < 0) {
1111 mailimf_address_free(addr);
1112 res = MAIL_ERROR_MEMORY;
1113 goto free_list;
1114 }
1115 }
1116
1117 addr_list = mailimf_address_list_new(list);
1118 if (addr_list == NULL) {
1119 res = MAIL_ERROR_MEMORY;
1120 goto free_list;
1121 }
1122
1123 * result = addr_list;
1124
1125 return MAIL_NO_ERROR;
1126
1127 free_list:
1128 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1129 clist_free(list);
1130 err:
1131 return res;
1132}
1133
1134static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index,
1135 struct mailimf_address * addr)
1136{
1137 int r;
1138
1139 r = mailimf_cache_int_write(mmapstr, index, addr->ad_type);
1140 if (r != MAIL_NO_ERROR)
1141 return r;
1142
1143 switch(addr->ad_type) {
1144 case MAILIMF_ADDRESS_MAILBOX:
1145 r = mailimf_cache_mailbox_write(mmapstr, index, addr->ad_data.ad_mailbox);
1146 if (r != MAIL_NO_ERROR)
1147 return r;
1148
1149 break;
1150
1151 case MAILIMF_ADDRESS_GROUP:
1152 r = mailimf_cache_group_write(mmapstr, index, addr->ad_data.ad_group);
1153 if (r != MAIL_NO_ERROR)
1154 return r;
1155
1156 break;
1157 }
1158
1159 return MAIL_NO_ERROR;
1160}
1161
1162static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index,
1163 struct mailimf_address ** result)
1164{
1165 uint32_t type;
1166 int r;
1167 struct mailimf_mailbox * mailbox;
1168 struct mailimf_group * group;
1169 struct mailimf_address * addr;
1170
1171 r = mailimf_cache_int_read(mmapstr, index, &type);
1172 if (r != MAIL_NO_ERROR)
1173 return r;
1174
1175 mailbox = NULL;
1176 group = NULL;
1177
1178 switch (type) {
1179 case MAILIMF_ADDRESS_MAILBOX:
1180 r = mailimf_cache_mailbox_read(mmapstr, index, &mailbox);
1181 if (r != MAIL_NO_ERROR)
1182 return r;
1183
1184 break;
1185
1186 case MAILIMF_ADDRESS_GROUP:
1187 r = mailimf_cache_group_read(mmapstr, index, &group);
1188 if (r != MAIL_NO_ERROR)
1189 return r;
1190
1191 break;
1192 }
1193
1194 addr = mailimf_address_new(type, mailbox, group);
1195 if (addr == NULL)
1196 goto free;
1197
1198 * result = addr;
1199
1200 return MAIL_NO_ERROR;
1201
1202 free:
1203 if (mailbox != NULL)
1204 mailimf_mailbox_free(mailbox);
1205 if (group != NULL)
1206 mailimf_group_free(group);
1207 return MAIL_ERROR_MEMORY;
1208}
1209
1210static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index,
1211 struct mailimf_group * group)
1212{
1213 int r;
1214
1215 r = mailimf_cache_string_write(mmapstr, index, group->grp_display_name,
1216 strlen(group->grp_display_name));
1217 if (r != MAIL_NO_ERROR)
1218 return r;
1219
1220 r = mailimf_cache_mailbox_list_write(mmapstr, index, group->grp_mb_list);
1221 if (r != MAIL_NO_ERROR)
1222 return r;
1223
1224 return MAIL_NO_ERROR;
1225}
1226
1227static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index,
1228 struct mailimf_group ** result)
1229{
1230 int r;
1231 char * display_name;
1232 struct mailimf_mailbox_list * mb_list;
1233 struct mailimf_group * group;
1234 int res;
1235
1236 r = mailimf_cache_string_read(mmapstr, index, &display_name);
1237 if (r != MAIL_NO_ERROR) {
1238 res = r;
1239 goto err;
1240 }
1241
1242 r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list);
1243 if (r != MAIL_NO_ERROR) {
1244 res = r;
1245 goto free_dsp_name;
1246 }
1247
1248 group = mailimf_group_new(display_name, mb_list);
1249 if (group == NULL) {
1250 res = MAIL_ERROR_MEMORY;
1251 goto free_mb_list;
1252 }
1253
1254 * result = group;
1255
1256 return MAIL_NO_ERROR;
1257
1258 free_mb_list:
1259 mailimf_mailbox_list_free(mb_list);
1260 free_dsp_name:
1261 free(display_name);
1262 err:
1263 return res;
1264}
1265
1266static int
1267mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * index,
1268 struct mailimf_mailbox_list * mb_list)
1269{
1270 clistiter * cur;
1271 int r;
1272
1273 if (mb_list == NULL) {
1274 r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER);
1275 if (r != MAIL_NO_ERROR)
1276 return r;
1277 }
1278 else {
1279 r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL);
1280 if (r != MAIL_NO_ERROR)
1281 return r;
1282
1283 r = mailimf_cache_int_write(mmapstr, index,
1284 clist_count(mb_list->mb_list));
1285 if (r != MAIL_NO_ERROR)
1286 return r;
1287
1288 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1289 cur = clist_next(cur)) {
1290 struct mailimf_mailbox * mb;
1291
1292 mb = clist_content(cur);
1293
1294 r = mailimf_cache_mailbox_write(mmapstr, index, mb);
1295 if (r != MAIL_NO_ERROR)
1296 return r;
1297 }
1298 }
1299
1300 return MAIL_NO_ERROR;
1301}
1302
1303static int
1304mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index,
1305 struct mailimf_mailbox_list ** result)
1306{
1307 clist * list;
1308 int r;
1309 uint32_t count;
1310 uint32_t i;
1311 struct mailimf_mailbox_list * mb_list;
1312 int res;
1313 uint32_t type;
1314
1315 r = mailimf_cache_int_read(mmapstr, index, &type);
1316 if (r != MAIL_NO_ERROR) {
1317 res = r;
1318 goto err;
1319 }
1320
1321 if (type == CACHE_NULL_POINTER) {
1322 * result = NULL;
1323 return MAIL_NO_ERROR;
1324 }
1325
1326 r = mailimf_cache_int_read(mmapstr, index, &count);
1327 if (r != MAIL_NO_ERROR) {
1328 res = r;
1329 goto err;
1330 }
1331
1332 list = clist_new();
1333 if (list == NULL) {
1334 res = MAIL_ERROR_MEMORY;
1335 goto err;
1336 }
1337
1338 for(i = 0 ; i < count ; i++) {
1339 struct mailimf_mailbox * mb;
1340
1341 r = mailimf_cache_mailbox_read(mmapstr, index, &mb);
1342 if (r != MAIL_NO_ERROR) {
1343 res = r;
1344 goto free_list;
1345 }
1346
1347 r = clist_append(list, mb);
1348 if (r < 0) {
1349 mailimf_mailbox_free(mb);
1350 res = MAIL_ERROR_MEMORY;
1351 goto free_list;
1352 }
1353 }
1354
1355 mb_list = mailimf_mailbox_list_new(list);
1356 if (mb_list == NULL) {
1357 res = MAIL_ERROR_MEMORY;
1358 goto free_list;
1359 }
1360
1361 * result = mb_list;
1362
1363 return MAIL_NO_ERROR;
1364
1365 free_list:
1366 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1367 clist_free(list);
1368 err:
1369 return res;
1370}
1371
1372static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index,
1373 struct mailimf_mailbox * mb)
1374{
1375 int r;
1376
1377 if (mb->mb_display_name) {
1378 r = mailimf_cache_string_write(mmapstr, index,
1379 mb->mb_display_name, strlen(mb->mb_display_name));
1380 if (r != MAIL_NO_ERROR)
1381 return r;
1382 }
1383 else {
1384 r = mailimf_cache_string_write(mmapstr, index, NULL, 0);
1385 if (r != MAIL_NO_ERROR)
1386 return r;
1387 }
1388
1389 r = mailimf_cache_string_write(mmapstr, index,
1390 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1391 if (r != MAIL_NO_ERROR)
1392 return r;
1393
1394 return MAIL_NO_ERROR;
1395}
1396
1397static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index,
1398 struct mailimf_mailbox ** result)
1399{
1400 int r;
1401 char * dsp_name;
1402 char * addr_spec;
1403 struct mailimf_mailbox * mb;
1404
1405 dsp_name = NULL;
1406
1407 r = mailimf_cache_string_read(mmapstr, index, &dsp_name);
1408 if (r != MAIL_NO_ERROR)
1409 return r;
1410
1411 r = mailimf_cache_string_read(mmapstr, index, &addr_spec);
1412 if (r != MAIL_NO_ERROR)
1413 goto free_dsp_name;
1414
1415 mb = mailimf_mailbox_new(dsp_name, addr_spec);
1416 if (mb == NULL)
1417 goto free_addr;
1418
1419 * result = mb;
1420
1421 return MAIL_NO_ERROR;
1422
1423 free_addr:
1424 free(addr_spec);
1425 free_dsp_name:
1426 if (dsp_name != NULL)
1427 free(dsp_name);
1428 return MAIL_ERROR_MEMORY;
1429}
diff --git a/libetpan/src/driver/tools/imfcache.h b/libetpan/src/driver/tools/imfcache.h
new file mode 100644
index 0000000..f054a12
--- a/dev/null
+++ b/libetpan/src/driver/tools/imfcache.h
@@ -0,0 +1,75 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMFCACHE_H
37
38#define IMFCACHE_H
39
40#include <stdio.h>
41#include "mailimf.h"
42#include "maildriver_types.h"
43#include "mmapstring.h"
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49int mail_serialize_clear(MMAPString * mmapstr, size_t * index);
50
51int mail_serialize_write(MMAPString * mmapstr, size_t * index,
52 char * buf, size_t size);
53
54int mail_serialize_read(MMAPString * mmapstr, size_t * index,
55 char * buf, size_t size);
56
57int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index,
58 uint32_t value);
59int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index,
60 char * str, size_t length);
61int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index,
62 uint32_t * result);
63int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index,
64 char ** result);
65
66int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index,
67 struct mailimf_fields * fields);
68int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index,
69 struct mailimf_fields ** result);
70
71#ifdef __cplusplus
72}
73#endif
74
75#endif
diff --git a/libetpan/src/driver/tools/mailthread.c b/libetpan/src/driver/tools/mailthread.c
new file mode 100644
index 0000000..32f73cd
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread.c
@@ -0,0 +1,1742 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailthread.h"
37#include "mailthread_types.h"
38
39#include <string.h>
40#include <time.h>
41#include <stdlib.h>
42#include <ctype.h>
43
44#include "mail.h"
45#include "chash.h"
46#include "carray.h"
47#include "clist.h"
48#include "mailmessage.h"
49
50static inline char * get_msg_id(mailmessage * msg)
51{
52 if (msg->msg_single_fields.fld_message_id != NULL)
53 return msg->msg_single_fields.fld_message_id->mid_value;
54 else
55 return NULL;
56}
57
58static inline clist * get_ref(mailmessage * msg)
59{
60 if (msg->msg_single_fields.fld_references != NULL)
61 return msg->msg_single_fields.fld_references->mid_list;
62 else
63 return NULL;
64}
65
66static inline clist * get_in_reply_to(mailmessage * msg)
67{
68 if (msg->msg_single_fields.fld_in_reply_to != NULL)
69 return msg->msg_single_fields.fld_in_reply_to->mid_list;
70 else
71 return NULL;
72}
73
74static inline int skip_subj_blob(char * subj, size_t * begin,
75 size_t length)
76{
77 /* subj-blob = "[" *BLOBCHAR "]" *WSP */
78 size_t cur_token;
79
80 cur_token = * begin;
81
82 if (subj[cur_token] != '[')
83 return FALSE;
84
85 cur_token ++;
86
87 while (1) {
88 if (cur_token >= length)
89 return FALSE;
90
91 if (subj[cur_token] == '[')
92 return FALSE;
93
94 if (subj[cur_token] == ']')
95 break;
96
97 cur_token ++;
98 }
99
100 cur_token ++;
101
102 while (1) {
103 if (cur_token >= length)
104 break;
105
106 if (subj[cur_token] != ' ')
107 break;
108
109 cur_token ++;
110 }
111
112 * begin = cur_token;
113
114 return TRUE;
115}
116
117static inline int skip_subj_refwd(char * subj, size_t * begin,
118 size_t length)
119{
120 /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */
121 size_t cur_token;
122 int prefix;
123
124 cur_token = * begin;
125
126 prefix = FALSE;
127 if (length >= 3) {
128 if (strncasecmp(subj + cur_token, "fwd", 3) == 0) {
129 cur_token += 3;
130 prefix = TRUE;
131 }
132 }
133 if (!prefix) {
134 if (length >= 2) {
135 if (strncasecmp(subj + cur_token, "fw", 2) == 0) {
136 cur_token += 2;
137 prefix = TRUE;
138 }
139 else if (strncasecmp(subj + cur_token, "re", 2) == 0) {
140 cur_token += 2;
141 prefix = TRUE;
142 }
143 }
144 }
145
146 if (!prefix)
147 return FALSE;
148
149 while (1) {
150 if (cur_token >= length)
151 break;
152
153 if (subj[cur_token] != ' ')
154 break;
155
156 cur_token ++;
157 }
158
159 skip_subj_blob(subj, &cur_token, length);
160
161 if (subj[cur_token] != ':')
162 return FALSE;
163
164 cur_token ++;
165
166 * begin = cur_token;
167
168 return TRUE;
169}
170
171static inline int skip_subj_leader(struct mailmessage_tree * tree,
172 char * subj, size_t * begin,
173 size_t length)
174{
175 size_t cur_token;
176
177 cur_token = * begin;
178
179 /* subj-leader = (*subj-blob subj-refwd) / WSP */
180
181 if (subj[cur_token] == ' ') {
182 cur_token ++;
183 }
184 else {
185 while (cur_token < length) {
186 if (!skip_subj_blob(subj, &cur_token, length))
187 break;
188 }
189 if (!skip_subj_refwd(subj, &cur_token, length))
190 return FALSE;
191 tree->node_is_reply = TRUE;
192 }
193
194 * begin = cur_token;
195
196 return TRUE;
197}
198
199
200static char * extract_subject(char * default_from,
201 struct mailmessage_tree * tree,
202 char * str)
203{
204 char * subj;
205 char * cur;
206 char * write_pos;
207 size_t len;
208 size_t begin;
209
210 char * decoded;
211 size_t cur_token;
212
213 int do_repeat_5;
214 int do_repeat_6;
215 int r;
216
217 /*
218 (1) Convert any RFC 2047 encoded-words in the subject to
219 UTF-8.
220 */
221
222 decoded = NULL;
223
224 cur_token = 0;
225 r = mailmime_encoded_phrase_parse(default_from, str, strlen(str),
226 &cur_token, "utf-8",
227 &decoded);
228
229 if (r == MAILIMF_NO_ERROR) {
230 subj = decoded;
231 }
232 else
233 subj = strdup(str);
234
235 len = strlen(subj);
236
237 /*
238 Convert all tabs and continuations to space.
239 Convert all multiple spaces to a single space.
240 */
241
242 cur = subj;
243 write_pos = subj;
244 while (* cur != '\0') {
245 int cont;
246
247 switch (* cur) {
248 case '\t':
249 case '\r':
250 case '\n':
251 cont = TRUE;
252
253 cur ++;
254 while (* cur && cont) {
255 switch (* cur) {
256 case '\t':
257 case '\r':
258 case '\n':
259 cont = TRUE;
260 break;
261 default:
262 cont = FALSE;
263 break;
264 }
265 cur ++;
266 }
267
268 * write_pos = ' ';
269 write_pos ++;
270
271 break;
272
273 default:
274 * write_pos = * cur;
275 write_pos ++;
276
277 cur ++;
278
279 break;
280 }
281 }
282 * write_pos = '\0';
283
284 begin = 0;
285
286 do {
287 do_repeat_6 = FALSE;
288
289 /*
290 (2) Remove all trailing text of the subject that matches
291 the subj-trailer ABNF, repeat until no more matches are
292 possible.
293 */
294
295 while (len > 0) {
296 int chg;
297
298 chg = FALSE;
299
300 /* subj-trailer = "(fwd)" / WSP */
301 if (subj[len - 1] == ' ') {
302 subj[len - 1] = '\0';
303 len --;
304 }
305 else {
306 if (len < 5)
307 break;
308
309 if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0)
310 break;
311
312 subj[len - 5] = '\0';
313 len -= 5;
314 tree->node_is_reply = TRUE;
315 }
316 }
317
318 do {
319 size_t saved_begin;
320
321 do_repeat_5 = FALSE;
322
323 /*
324 (3) Remove all prefix text of the subject that matches the
325 subj-leader ABNF.
326 */
327
328 if (skip_subj_leader(tree, subj, &begin, len))
329 do_repeat_5 = TRUE;
330
331 /*
332 (4) If there is prefix text of the subject that matches the
333 subj-blob ABNF, and removing that prefix leaves a non-empty
334 subj-base, then remove the prefix text.
335 */
336
337 saved_begin = begin;
338 if (skip_subj_blob(subj, &begin, len)) {
339 if (begin == len) {
340 /* this will leave a empty subject base */
341 begin = saved_begin;
342 }
343 else
344 do_repeat_5 = TRUE;
345 }
346
347 /*
348 (5) Repeat (3) and (4) until no matches remain.
349 Note: it is possible to defer step (2) until step (6),
350 but this requires checking for subj-trailer in step (4).
351 */
352
353 }
354 while (do_repeat_5);
355
356 /*
357 (6) If the resulting text begins with the subj-fwd-hdr ABNF
358 and ends with the subj-fwd-trl ABNF, remove the
359 subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
360 */
361
362 if (len >= 5) {
363 size_t saved_begin;
364
365 saved_begin = begin;
366 if (strncasecmp(subj + begin, "[fwd:", 5) == 0) {
367 begin += 5;
368
369 if (subj[len - 1] != ']')
370 saved_begin = begin;
371 else {
372 tree->node_is_reply = TRUE;
373
374 subj[len - 1] = '\0';
375 len --;
376 do_repeat_6 = TRUE;
377 }
378 }
379 }
380
381 }
382 while (do_repeat_6);
383
384 /*
385 (7) The resulting text is the "base subject" used in
386 threading.
387 */
388
389 /* convert to upper case */
390
391 cur = subj + begin;
392 write_pos = subj;
393
394 while (* cur != '\0') {
395 * write_pos = (char) toupper((unsigned char) * cur);
396 cur ++;
397 write_pos ++;
398 }
399 * write_pos = '\0';
400
401 return subj;
402}
403
404static int get_extracted_subject(char * default_from,
405 struct mailmessage_tree * tree,
406 char ** result)
407{
408 if (tree->node_msg->msg_single_fields.fld_subject != NULL) {
409 char * subj;
410
411 subj = extract_subject(default_from,
412 tree, tree->node_msg->msg_single_fields.fld_subject->sbj_value);
413 if (subj == NULL)
414 return MAIL_ERROR_MEMORY;
415
416 * result = subj;
417
418 return MAIL_NO_ERROR;
419 }
420
421 return MAIL_ERROR_SUBJECT_NOT_FOUND;
422}
423
424static int get_thread_subject(char * default_from,
425 struct mailmessage_tree * tree,
426 char ** result)
427{
428 char * thread_subject;
429 int r;
430 unsigned int i;
431
432 if (tree->node_msg != NULL) {
433 if (tree->node_msg->msg_fields != NULL) {
434 r = get_extracted_subject(default_from, tree, &thread_subject);
435
436 if (r != MAIL_NO_ERROR)
437 return r;
438
439 * result = thread_subject;
440 return MAIL_NO_ERROR;
441 }
442 }
443
444 for(i = 0 ; i < carray_count(tree->node_children) ; i ++) {
445 struct mailmessage_tree * child;
446
447 child = carray_get(tree->node_children, i);
448
449 r = get_thread_subject(default_from, child, &thread_subject);
450
451 switch (r) {
452 case MAIL_NO_ERROR:
453 * result = thread_subject;
454 return MAIL_NO_ERROR;
455
456 case MAIL_ERROR_SUBJECT_NOT_FOUND:
457 /* do nothing */
458 break;
459
460 default:
461 return r;
462 }
463 }
464
465 return MAIL_ERROR_SUBJECT_NOT_FOUND;
466}
467
468
469
470#ifndef WRONG
471 #define WRONG(-1)
472#endif /* !defined WRONG */
473
474static int tmcomp(struct tm * atmp, struct tm * btmp)
475{
476 register intresult;
477
478 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
479 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
480 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
481 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
482 (result = (atmp->tm_min - btmp->tm_min)) == 0)
483 result = atmp->tm_sec - btmp->tm_sec;
484 return result;
485}
486
487static time_t mkgmtime(struct tm * tmp)
488{
489 register int dir;
490 register int bits;
491 register int saved_seconds;
492 time_t t;
493 struct tm yourtm, *mytm;
494
495 yourtm = *tmp;
496 saved_seconds = yourtm.tm_sec;
497 yourtm.tm_sec = 0;
498 /*
499 ** Calculate the number of magnitude bits in a time_t
500 ** (this works regardless of whether time_t is
501 ** signed or unsigned, though lint complains if unsigned).
502 */
503 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
504 ;
505 /*
506 ** If time_t is signed, then 0 is the median value,
507 ** if time_t is unsigned, then 1 << bits is median.
508 */
509 t = (t < 0) ? 0 : ((time_t) 1 << bits);
510 for ( ; ; ) {
511 mytm = gmtime(&t);
512 dir = tmcomp(mytm, &yourtm);
513 if (dir != 0) {
514 if (bits-- < 0)
515 return WRONG;
516 if (bits < 0)
517 --t;
518 else if (dir > 0)
519 t -= (time_t) 1 << bits;
520 elset += (time_t) 1 << bits;
521 continue;
522 }
523 break;
524 }
525 t += saved_seconds;
526 return t;
527}
528
529static inline time_t get_date(mailmessage * msg)
530{
531 struct tm tmval;
532 time_t timeval;
533 struct mailimf_date_time * date_time;
534
535 if (msg->msg_single_fields.fld_orig_date == NULL)
536 return (time_t) -1;
537
538 date_time = msg->msg_single_fields.fld_orig_date->dt_date_time;
539
540 tmval.tm_sec = date_time->dt_sec;
541 tmval.tm_min = date_time->dt_min;
542 tmval.tm_hour = date_time->dt_hour;
543 tmval.tm_sec = date_time->dt_sec;
544 tmval.tm_mday = date_time->dt_day;
545 tmval.tm_mon = date_time->dt_month - 1;
546 tmval.tm_year = date_time->dt_year - 1900;
547
548 timeval = mkgmtime(&tmval);
549
550 timeval -= date_time->dt_zone * 36;
551
552 return timeval;
553}
554
555static inline int is_descendant(struct mailmessage_tree * node,
556 struct mailmessage_tree * maybe_child)
557{
558 unsigned int i;
559
560 for(i = 0 ; i < carray_count(node->node_children) ; i++) {
561 struct mailmessage_tree * tree;
562
563 tree = carray_get(node->node_children, i);
564 if (tree == maybe_child)
565 return TRUE;
566 if (carray_count(tree->node_children) != 0)
567 if (is_descendant(tree, maybe_child))
568 return TRUE;
569 }
570
571 return FALSE;
572}
573
574static int delete_dummy(carray * rootlist, carray * sibling_list,
575 unsigned int cur, unsigned int * pnext)
576{
577 struct mailmessage_tree * env_tree;
578 int res;
579 int r;
580 unsigned int cur_child;
581 unsigned int next;
582
583 env_tree = carray_get(sibling_list, cur);
584
585 cur_child = 0;
586 while (cur_child < carray_count(env_tree->node_children)) {
587 delete_dummy(rootlist, env_tree->node_children, cur_child, &cur_child);
588 }
589
590 if (env_tree->node_msg == NULL) {
591 if (carray_count(env_tree->node_children) == 0) {
592
593 /* If it is a dummy message with NO children, delete it. */
594 mailmessage_tree_free(env_tree);
595 carray_delete(sibling_list, cur);
596 next = cur;
597 }
598 else {
599 /* If it is a dummy message with children, delete it, but
600 promote its children to the current level. */
601
602 /*
603 Do not promote the children if doing so would make them
604 children of the root, unless there is only one child.
605 */
606
607 cur_child = 0;
608 if ((sibling_list != rootlist) ||
609 (carray_count(env_tree->node_children) == 1)) {
610 while (cur_child < carray_count(env_tree->node_children)) {
611 struct mailmessage_tree * child;
612
613 child = carray_get(env_tree->node_children, cur_child);
614 r = carray_add(sibling_list, child, NULL);
615 if (r < 0) {
616 res = MAIL_ERROR_MEMORY;
617 goto err;
618 }
619 /* set new parent of the children */
620 child->node_parent = env_tree->node_parent;
621
622 carray_delete(env_tree->node_children, cur_child);
623 }
624 mailmessage_tree_free(env_tree);
625 carray_delete(sibling_list, cur);
626 next = cur;
627 }
628 else
629 next = cur + 1;
630 }
631 }
632 else
633 next = cur + 1;
634
635 * pnext = next;
636
637 return MAIL_NO_ERROR;
638
639 err:
640 return res;
641}
642
643static inline time_t tree_get_date(struct mailmessage_tree * tree)
644{
645 if (tree->node_msg != NULL) {
646 return tree->node_date;
647 }
648 else {
649 struct mailmessage_tree * subtree;
650
651 if (carray_count(tree->node_children) == 0)
652 return (time_t) -1;
653
654 subtree = carray_get(tree->node_children, 0);
655
656 return subtree->node_date;
657 }
658}
659
660static inline uint32_t tree_get_index(struct mailmessage_tree * tree)
661{
662 if (tree->node_msg == NULL)
663 return 0;
664
665 return tree->node_msg->msg_index;
666}
667
668int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1,
669 struct mailmessage_tree ** ptree2)
670{
671 time_t date1;
672 time_t date2;
673
674 date1 = tree_get_date(* ptree1);
675 date2 = tree_get_date(* ptree2);
676
677 if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) {
678 uint32_t index1;
679 uint32_t index2;
680
681 index1 = tree_get_index(* ptree1);
682 index2 = tree_get_index(* ptree2);
683 return (int) ((long) index1 - (long) index2);
684 }
685
686 return (int) ((long) date1 - (long) date2);
687}
688
689static int tree_subj_time_comp(struct mailmessage_tree ** ptree1,
690 struct mailmessage_tree ** ptree2)
691{
692 char * subj1;
693 char * subj2;
694 time_t date1;
695 time_t date2;
696 int r;
697
698 subj1 = (* ptree1)->node_base_subject;
699 subj2 = (* ptree2)->node_base_subject;
700
701 if ((subj1 != NULL) && (subj2 != NULL))
702 r = strcmp(subj1, subj2);
703 else {
704 if ((subj1 == NULL) && (subj2 == NULL))
705 r = 0;
706 else if (subj1 == NULL)
707 r = -1;
708 else /* subj2 == NULL */
709 r = 1;
710 }
711
712 if (r != 0)
713 return r;
714
715 date1 = (* ptree1)->node_date;
716 date2 = (* ptree2)->node_date;
717
718 if ((date1 == (time_t) -1) || (date2 == (time_t) -1))
719 return ((int32_t) (* ptree1)->node_msg->msg_index) -
720 ((int32_t) (* ptree2)->node_msg->msg_index);
721
722 return (int) ((long) date1 - (long) date2);
723}
724
725
726
727int mail_thread_sort(struct mailmessage_tree * tree,
728 int (* comp_func)(struct mailmessage_tree **,
729 struct mailmessage_tree **),
730 int sort_sub)
731{
732 unsigned int cur;
733 int r;
734 int res;
735
736 for(cur = 0 ; cur < carray_count(tree->node_children) ; cur ++) {
737 struct mailmessage_tree * subtree;
738
739 subtree = carray_get(tree->node_children, cur);
740
741 if (sort_sub) {
742 r = mail_thread_sort(subtree, comp_func, sort_sub);
743 if (r != MAIL_NO_ERROR) {
744 res = r;
745 goto err;
746 }
747 }
748 }
749
750 qsort(carray_data(tree->node_children), carray_count(tree->node_children),
751 sizeof(struct mailmessage_tree *),
752 (int (*)(const void *, const void *)) comp_func);
753
754 return MAIL_NO_ERROR;
755
756 err:
757 return res;
758}
759
760
761static int
762mail_build_thread_references(char * default_from,
763 struct mailmessage_list * env_list,
764 struct mailmessage_tree ** result,
765 int use_subject,
766 int (* comp_func)(struct mailmessage_tree **,
767 struct mailmessage_tree **))
768{
769 int r;
770 int res;
771 chash * msg_id_hash;
772 unsigned int cur;
773 struct mailmessage_tree * root;
774 carray * rootlist;
775 carray * msg_list;
776 unsigned int i;
777 chash * subject_hash;
778
779 msg_id_hash = chash_new(128, CHASH_COPYNONE);
780 if (msg_id_hash == NULL) {
781 res = MAIL_ERROR_MEMORY;
782 goto err;
783 }
784
785 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
786 if (root == NULL) {
787 res = MAIL_ERROR_MEMORY;
788 goto free_hash;
789 }
790 rootlist = root->node_children;
791
792 msg_list = carray_new(128);
793 if (msg_list == NULL) {
794 res = MAIL_ERROR_MEMORY;
795 goto free_root;
796 }
797
798 /* collect message-ID */
799 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
800 mailmessage * msg;
801 char * msgid;
802 struct mailmessage_tree * env_tree;
803 chashdatum hashkey;
804 chashdatum hashdata;
805 chashdatum hashold;
806 time_t date;
807
808 msg = carray_get(env_list->msg_tab, i);
809
810 if (msg == NULL)
811 continue;
812
813 if (msg->msg_fields != NULL) {
814 msgid = get_msg_id(msg);
815
816 if (msgid == NULL) {
817 msgid = mailimf_get_message_id();
818 }
819 else {
820 hashkey.data = msgid;
821 hashkey.len = strlen(msgid);
822
823 if (chash_get(msg_id_hash, &hashkey, &hashdata) == 0)
824 msgid = mailimf_get_message_id();
825 else
826 msgid = strdup(msgid);
827 }
828
829 if (msgid == NULL) {
830 res = MAIL_ERROR_MEMORY;
831 goto free_list;
832 }
833
834 date = get_date(msg);
835
836 env_tree = mailmessage_tree_new(msgid, date, msg);
837 if (env_tree == NULL) {
838 res = MAIL_ERROR_MEMORY;
839 goto free_list;
840 }
841
842 r = carray_add(msg_list, env_tree, NULL);
843 if (r < 0) {
844 mailmessage_tree_free(env_tree);
845 res = MAIL_ERROR_MEMORY;
846 goto free_list;
847 }
848
849 hashkey.data = msgid;
850 hashkey.len = strlen(msgid);
851
852 hashdata.data = env_tree;
853 hashdata.len = 0;
854
855 r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold);
856 if (r < 0) {
857 res = MAIL_ERROR_MEMORY;
858 goto free_list;
859 }
860 }
861 }
862
863 /* (1) for all messages */
864
865 for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) {
866 struct mailmessage_tree * env_tree;
867 mailmessage * msg;
868 clist * ref;
869
870 env_tree = carray_get(msg_list, cur);
871
872 msg = env_tree->node_msg;
873
874 ref = NULL;
875 if (msg != NULL) {
876 ref = get_ref(msg);
877 if (ref == NULL)
878 ref = get_in_reply_to(msg);
879 }
880
881 /* (A) Using the Message IDs in the message's references, link
882 the corresponding messages (those whose Message-ID header
883 line contains the given reference Message ID) together as
884 parent/child.
885 */
886
887 if (ref != NULL) {
888 /* try to start a tree */
889
890 clistiter * cur_ref;
891 chashdatum hashkey;
892 chashdatum hashdata;
893 chashdatum hashold;
894 struct mailmessage_tree * env_cur_tree;
895 struct mailmessage_tree * last_env_cur_tree;
896
897 env_cur_tree = NULL;
898 for(cur_ref = clist_begin(ref) ; cur_ref != NULL ;
899 cur_ref = clist_next(cur_ref)) {
900 char * msgid;
901
902 last_env_cur_tree = env_cur_tree;
903
904 msgid = clist_content(cur_ref);
905
906 hashkey.data = msgid;
907 hashkey.len = strlen(msgid);
908
909 r = chash_get(msg_id_hash, &hashkey, &hashdata);
910 if (r < 0) {
911 /* not found, create a dummy message */
912 msgid = strdup(msgid);
913 if (msgid == NULL) {
914 res = MAIL_ERROR_MEMORY;
915 goto free_list;
916 }
917
918 env_cur_tree = mailmessage_tree_new(msgid, (time_t) -1, NULL);
919 if (env_cur_tree == NULL) {
920 free(msgid);
921 res = MAIL_ERROR_MEMORY;
922 goto free_list;
923 }
924
925 r = carray_add(msg_list, env_cur_tree, NULL);
926 if (r < 0) {
927 mailmessage_tree_free(env_cur_tree);
928 res = MAIL_ERROR_MEMORY;
929 goto free_list;
930 }
931
932 hashkey.data = msgid;
933 hashkey.len = strlen(msgid);
934
935 hashdata.data = env_cur_tree;
936 hashdata.len = 0;
937
938 r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold);
939 if (r < 0) {
940 res = MAIL_ERROR_MEMORY;
941 goto free_list;
942 }
943 }
944 else {
945 env_cur_tree = hashdata.data;
946 }
947
948 if (last_env_cur_tree != NULL) {
949 if (env_cur_tree->node_parent == NULL) {
950 /* make it one child */
951 if (env_cur_tree != last_env_cur_tree) {
952 if (!is_descendant(env_cur_tree, last_env_cur_tree)) {
953 /* set parent */
954 env_cur_tree->node_parent = last_env_cur_tree;
955 r = carray_add(last_env_cur_tree->node_children,
956 env_cur_tree, NULL);
957 if (r < 0) {
958 res = MAIL_ERROR_MEMORY;
959 goto free_list;
960 }
961 }
962 }
963 }
964 }
965 }
966
967 /* (B) Create a parent/child link between the last reference
968 (or NIL if there are no references) and the current message.
969 If the current message already has a parent, it is probably
970 the result of a truncated References header line, so break
971 the current parent/child link before creating the new
972 correct one.
973 */
974
975 last_env_cur_tree = env_cur_tree;
976
977 if (last_env_cur_tree != NULL) {
978 if (env_tree->node_parent == NULL) {
979 if (last_env_cur_tree != env_tree) {
980 if (!is_descendant(env_tree, last_env_cur_tree)) {
981 /* set parent */
982 env_tree->node_parent = last_env_cur_tree;
983 r = carray_add(last_env_cur_tree->node_children, env_tree, NULL);
984 if (r < 0) {
985 res = MAIL_ERROR_MEMORY;
986 goto free_list;
987 }
988 }
989 }
990 }
991 }
992 }
993 }
994
995 chash_free(msg_id_hash);
996 msg_id_hash = NULL;
997
998 /* (2) Gather together all of the messages that have no parents
999 and make them all children (siblings of one another) of a dummy
1000 parent (the "root").
1001 */
1002
1003 for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) {
1004 struct mailmessage_tree * env_tree;
1005
1006 env_tree = carray_get(msg_list, cur);
1007 if (env_tree->node_parent == NULL) {
1008 r = carray_add(rootlist, env_tree, NULL);
1009 if (r < 0) {
1010 res = MAIL_ERROR_MEMORY;
1011 goto free_list;
1012 }
1013 /* set parent */
1014 env_tree->node_parent = root;
1015 }
1016 }
1017
1018 carray_free(msg_list);
1019 msg_list = NULL;
1020
1021 /* (3) Prune dummy messages from the thread tree.
1022 */
1023
1024 cur = 0;
1025 while (cur < carray_count(rootlist)) {
1026 r = delete_dummy(rootlist, rootlist, cur, &cur);
1027 if (r != MAIL_NO_ERROR) {
1028 res = r;
1029 goto free_list;
1030 }
1031 }
1032
1033 /* (4) Sort the messages under the root (top-level siblings only)
1034 by sent date.
1035 */
1036
1037 r = mail_thread_sort(root, mailthread_tree_timecomp, FALSE);
1038 if (r != MAIL_NO_ERROR) {
1039 res = r;
1040 goto free_list;
1041 }
1042
1043 if (use_subject) {
1044
1045 /* (5) Gather together messages under the root that have the same
1046 extracted subject text.
1047
1048 (A) Create a table for associating extracted subjects with
1049 messages.
1050 */
1051
1052 subject_hash = chash_new(128, CHASH_COPYVALUE);
1053 if (subject_hash == NULL) {
1054 res = MAIL_ERROR_MEMORY;
1055 goto free_list;
1056 }
1057
1058 /*
1059 (B) Populate the subject table with one message per
1060 extracted subject. For each child of the root:
1061 */
1062
1063 for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) {
1064 struct mailmessage_tree * env_tree;
1065 chashdatum key;
1066 chashdatum data;
1067 char * base_subject;
1068 int r;
1069
1070 env_tree = carray_get(rootlist, cur);
1071
1072 /*
1073 (i) Find the subject of this thread by extracting the
1074 base subject from the current message, or its first child
1075 if the current message is a dummy.
1076 */
1077
1078 r = get_thread_subject(default_from, env_tree, &base_subject);
1079
1080 /*
1081 (ii) If the extracted subject is empty, skip this
1082 message.
1083 */
1084
1085 if (r == MAIL_ERROR_SUBJECT_NOT_FOUND) {
1086 /* no subject found */
1087 continue;
1088 }
1089 else if (r == MAIL_NO_ERROR) {
1090 if (* base_subject == '\0') {
1091 /* subject empty */
1092 free(base_subject);
1093 continue;
1094 }
1095 else {
1096 /* do nothing */
1097 }
1098 }
1099 else {
1100 res = r;
1101 goto free_subject_hash;
1102 }
1103
1104 env_tree->node_base_subject = base_subject;
1105
1106 /*
1107 (iii) Lookup the message associated with this extracted
1108 subject in the table.
1109 */
1110
1111 key.data = base_subject;
1112 key.len = strlen(base_subject);
1113
1114 r = chash_get(subject_hash, &key, &data);
1115
1116 if (r < 0) {
1117 /*
1118 (iv) If there is no message in the table with this
1119 subject, add the current message and the extracted
1120 subject to the subject table.
1121 */
1122
1123 data.data = &cur;
1124 data.len = sizeof(cur);
1125
1126 r = chash_set(subject_hash, &key, &data, NULL);
1127 if (r < 0) {
1128 res = MAIL_ERROR_MEMORY;
1129 goto free_subject_hash;
1130 }
1131 }
1132 else {
1133 /*
1134 Otherwise, replace the message in the table with the
1135 current message if the message in the table is not a
1136 dummy AND either of the following criteria are true:
1137 The current message is a dummy, OR
1138 The message in the table is a reply or forward (its
1139 original subject contains a subj-refwd part and/or a
1140 "(fwd)" subj-trailer) and the current message is not.
1141 */
1142 struct mailmessage_tree * msg_in_table;
1143 unsigned int * iter_in_table;
1144 int replace;
1145
1146 iter_in_table = data.data;
1147 msg_in_table = carray_get(rootlist, cur);
1148
1149 replace = FALSE;
1150 /* message is dummy if info is NULL */
1151 if (msg_in_table->node_msg != NULL) {
1152
1153 if (env_tree->node_msg == NULL)
1154 replace = TRUE;
1155 else {
1156 if (env_tree->node_is_reply && !env_tree->node_is_reply)
1157 replace = TRUE;
1158 }
1159 }
1160
1161 if (replace) {
1162 data.data = &cur;
1163 data.len = sizeof(cur);
1164
1165 r = chash_set(subject_hash, &key, &data, NULL);
1166 if (r < 0) {
1167 res = MAIL_ERROR_MEMORY;
1168 goto free_subject_hash;
1169 }
1170 }
1171 }
1172 }
1173
1174 /*
1175 (C) Merge threads with the same subject. For each child of
1176 the root:
1177 */
1178
1179 cur = 0;
1180 while (cur < carray_count(rootlist)) {
1181 struct mailmessage_tree * env_tree;
1182 chashdatum key;
1183 chashdatum data;
1184 int r;
1185 struct mailmessage_tree * main_tree;
1186 unsigned int * main_cur;
1187
1188 env_tree = carray_get(rootlist, cur);
1189
1190 if (env_tree == NULL)
1191 goto next_msg;
1192
1193 /*
1194 (i) Find the subject of this thread as in step 4.B.i
1195 above.
1196 */
1197
1198 /* already done in tree->node_base_subject */
1199
1200 /*
1201 (ii) If the extracted subject is empty, skip this
1202 message.
1203 */
1204
1205 if (env_tree->node_base_subject == NULL)
1206 goto next_msg;
1207
1208 if (* env_tree->node_base_subject == '\0')
1209 goto next_msg;
1210
1211 /*
1212 (iii) Lookup the message associated with this extracted
1213 subject in the table.
1214 */
1215
1216 key.data = env_tree->node_base_subject;
1217 key.len = strlen(env_tree->node_base_subject);
1218
1219 r = chash_get(subject_hash, &key, &data);
1220 if (r < 0)
1221 goto next_msg;
1222
1223 /*
1224 (iv) If the message in the table is the current message,
1225 skip this message.
1226 */
1227
1228 main_cur = data.data;
1229 if (* main_cur == cur)
1230 goto next_msg;
1231
1232 /*
1233 Otherwise, merge the current message with the one in the
1234 table using the following rules:
1235 */
1236
1237 main_tree = carray_get(rootlist, * main_cur);
1238
1239 /*
1240 If both messages are dummies, append the current
1241 message's children to the children of the message in
1242 the table (the children of both messages become
1243 siblings), and then delete the current message.
1244 */
1245
1246 if ((env_tree->node_msg == NULL) && (main_tree->node_msg == NULL)) {
1247 unsigned int old_size;
1248
1249 old_size = carray_count(main_tree->node_children);
1250
1251 r = carray_set_size(main_tree->node_children, old_size +
1252 carray_count(env_tree->node_children));
1253 if (r < 0) {
1254 res = MAIL_ERROR_MEMORY;
1255 goto free_subject_hash;
1256 }
1257
1258 for(i = 0 ; i < carray_count(env_tree->node_children) ; i ++) {
1259 struct mailmessage_tree * child;
1260
1261 child = carray_get(env_tree->node_children, i);
1262 carray_set(main_tree->node_children, old_size + i, child);
1263 /* set parent */
1264 child->node_parent = main_tree;
1265 }
1266 carray_set_size(env_tree->node_children, 0);
1267 /* this is the only case where children can be NULL,
1268 this is before freeing it */
1269 mailmessage_tree_free(env_tree);
1270 carray_delete_fast(rootlist, cur);
1271 }
1272
1273 /*
1274 If the message in the table is a dummy and the current
1275 message is not, make the current message a child of
1276 the message in the table (a sibling of it's children).
1277 */
1278
1279 else if (main_tree->node_msg == NULL) {
1280 r = carray_add(main_tree->node_children, env_tree, NULL);
1281 if (r < 0) {
1282 res = MAIL_ERROR_MEMORY;
1283 goto free_subject_hash;
1284 }
1285 /* set parent */
1286 env_tree->node_parent = main_tree;
1287
1288 carray_delete_fast(rootlist, cur);
1289 }
1290
1291 /*
1292 If the current message is a reply or forward and the
1293 message in the table is not, make the current message
1294 a child of the message in the table (a sibling of it's
1295 children).
1296 */
1297
1298 else if (env_tree->node_is_reply && !main_tree->node_is_reply) {
1299 r = carray_add(main_tree->node_children, env_tree, NULL);
1300 if (r < 0) {
1301 res = MAIL_ERROR_MEMORY;
1302 goto free_subject_hash;
1303 }
1304 /* set parent */
1305 env_tree->node_parent = main_tree;
1306
1307 carray_delete_fast(rootlist, cur);
1308 }
1309
1310 /*
1311 Otherwise, create a new dummy message and make both
1312 the current message and the message in the table
1313 children of the dummy. Then replace the message in
1314 the table with the dummy message.
1315 Note: Subject comparisons are case-insensitive, as
1316 described under "Internationalization
1317 Considerations."
1318 */
1319
1320 else {
1321 struct mailmessage_tree * new_main_tree;
1322 char * base_subject;
1323 unsigned int last;
1324
1325 new_main_tree = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1326 if (new_main_tree == NULL) {
1327 res = MAIL_ERROR_MEMORY;
1328 goto free_subject_hash;
1329 }
1330
1331 /* main_tree->node_base_subject is never NULL */
1332
1333 base_subject = strdup(main_tree->node_base_subject);
1334 if (base_subject == NULL) {
1335 mailmessage_tree_free(new_main_tree);
1336 res = MAIL_ERROR_MEMORY;
1337 goto free_subject_hash;
1338 }
1339
1340 new_main_tree->node_base_subject = base_subject;
1341
1342 r = carray_add(rootlist, new_main_tree, &last);
1343 if (r < 0) {
1344 mailmessage_tree_free(new_main_tree);
1345 res = MAIL_ERROR_MEMORY;
1346 goto free_subject_hash;
1347 }
1348
1349 r = carray_add(new_main_tree->node_children, main_tree, NULL);
1350 if (r < 0) {
1351 res = MAIL_ERROR_MEMORY;
1352 goto free_subject_hash;
1353 }
1354 /* set parent */
1355 main_tree->node_parent = new_main_tree;
1356
1357 carray_delete_fast(rootlist, * main_cur);
1358
1359 r = carray_add(new_main_tree->node_children, env_tree, NULL);
1360 if (r < 0) {
1361 res = MAIL_ERROR_MEMORY;
1362 goto free_subject_hash;
1363 }
1364 /* set parent */
1365 env_tree->node_parent = new_main_tree;
1366
1367 carray_delete_fast(rootlist, cur);
1368
1369 data.data = &last;
1370 data.len = sizeof(last);
1371
1372 r = chash_set(subject_hash, &key, &data, NULL);
1373
1374 if (r < 0) {
1375 res = MAIL_ERROR_MEMORY;
1376 goto free_subject_hash;
1377 }
1378 }
1379
1380 continue;
1381
1382 next_msg:
1383 cur ++;
1384 continue;
1385 }
1386
1387 i = 0;
1388 for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) {
1389 struct mailmessage_tree * env_tree;
1390
1391 env_tree = carray_get(rootlist, cur);
1392 if (env_tree == NULL)
1393 continue;
1394
1395 carray_set(rootlist, i, env_tree);
1396 i ++;
1397 }
1398 carray_set_size(rootlist, i);
1399
1400 chash_free(subject_hash);
1401 }
1402
1403 /*
1404 (6) Traverse the messages under the root and sort each set of
1405 siblings by sent date. Traverse the messages in such a way
1406 that the "youngest" set of siblings are sorted first, and the
1407 "oldest" set of siblings are sorted last (grandchildren are
1408 sorted before children, etc).
1409
1410 In the case of an exact match on
1411 sent date or if either of the Date: headers used in a
1412 comparison can not be parsed, use the order in which the
1413 messages appear in the mailbox (that is, by sequence number) to
1414 determine the order. In the case of a dummy message (which can
1415 only occur with top-level siblings), use its first child for
1416 sorting.
1417 */
1418
1419#if 0
1420 if (comp_func != NULL) {
1421 r = mail_thread_sort(root, comp_func, TRUE);
1422 if (r != MAIL_NO_ERROR) {
1423 res = r;
1424 goto free_list;
1425 }
1426 }
1427#endif
1428 if (comp_func == NULL)
1429 comp_func = mailthread_tree_timecomp;
1430
1431 r = mail_thread_sort(root, comp_func, TRUE);
1432 if (r != MAIL_NO_ERROR) {
1433 res = r;
1434 goto free_list;
1435 }
1436
1437 * result = root;
1438
1439 return MAIL_NO_ERROR;
1440
1441 free_subject_hash:
1442 chash_free(subject_hash);
1443 free_list:
1444 if (msg_list != NULL) {
1445 for(i = 0 ; i < carray_count(msg_list) ; i ++)
1446 mailmessage_tree_free(carray_get(msg_list, i));
1447 carray_free(msg_list);
1448 }
1449 free_root:
1450 mailmessage_tree_free_recursive(root);
1451 free_hash:
1452 if (msg_id_hash != NULL)
1453 chash_free(msg_id_hash);
1454 err:
1455 return res;
1456}
1457
1458
1459
1460static int
1461mail_build_thread_orderedsubject(char * default_from,
1462 struct mailmessage_list * env_list,
1463 struct mailmessage_tree ** result,
1464 int (* comp_func)(struct mailmessage_tree **,
1465 struct mailmessage_tree **))
1466{
1467 unsigned int i;
1468 carray * rootlist;
1469 unsigned int cur;
1470 struct mailmessage_tree * root;
1471 int res;
1472 int r;
1473 struct mailmessage_tree * current_thread;
1474
1475 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1476 if (root == NULL) {
1477 res = MAIL_ERROR_MEMORY;
1478 goto err;
1479 }
1480 rootlist = root->node_children;
1481
1482 /*
1483 The ORDEREDSUBJECT threading algorithm is also referred to as
1484 "poor man's threading."
1485 */
1486
1487 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1488 mailmessage * msg;
1489 struct mailmessage_tree * env_tree;
1490 char * base_subject;
1491 time_t date;
1492
1493 msg = carray_get(env_list->msg_tab, i);
1494
1495 if (msg == NULL)
1496 continue;
1497
1498 if (msg->msg_fields != NULL) {
1499
1500 date = get_date(msg);
1501
1502 env_tree = mailmessage_tree_new(NULL, date, msg);
1503 if (env_tree == NULL) {
1504 res = MAIL_ERROR_MEMORY;
1505 goto free;
1506 }
1507
1508 /* set parent */
1509 env_tree->node_parent = root;
1510 r = carray_add(rootlist, env_tree, NULL);
1511 if (r < 0) {
1512 mailmessage_tree_free(env_tree);
1513 res = MAIL_ERROR_MEMORY;
1514 goto free;
1515 }
1516
1517 r = get_extracted_subject(default_from, env_tree, &base_subject);
1518 switch (r) {
1519 case MAIL_NO_ERROR:
1520 env_tree->node_base_subject = base_subject;
1521 break;
1522
1523 case MAIL_ERROR_SUBJECT_NOT_FOUND:
1524 break;
1525
1526 default:
1527 res = r;
1528 goto free;
1529 }
1530 }
1531 }
1532
1533 /*
1534 The searched messages are sorted by
1535 subject and then by the sent date.
1536 */
1537
1538 r = mail_thread_sort(root, tree_subj_time_comp, FALSE);
1539 if (r != MAIL_NO_ERROR) {
1540 res = r;
1541 goto free;
1542 }
1543
1544 /*
1545 The messages are then split
1546 into separate threads, with each thread containing messages
1547 with the same extracted subject text.
1548 */
1549
1550 current_thread = NULL;
1551
1552 cur = 0;
1553 while (cur < carray_count(rootlist)) {
1554 struct mailmessage_tree * cur_env_tree;
1555
1556 cur_env_tree = carray_get(rootlist, cur);
1557 if (current_thread == NULL) {
1558 current_thread = cur_env_tree;
1559 cur ++;
1560 continue;
1561 }
1562
1563 if ((cur_env_tree->node_base_subject == NULL) ||
1564 (current_thread->node_base_subject == NULL)) {
1565 current_thread = cur_env_tree;
1566 cur ++;
1567 continue;
1568 }
1569
1570 if (strcmp(cur_env_tree->node_base_subject,
1571 current_thread->node_base_subject) == 0) {
1572
1573 /* set parent */
1574 cur_env_tree->node_parent = current_thread;
1575 r = carray_add(current_thread->node_children, cur_env_tree, NULL);
1576 if (r < 0) {
1577 res = MAIL_ERROR_MEMORY;
1578 goto free;
1579 }
1580
1581 carray_delete(rootlist, cur);
1582 }
1583 else
1584 cur ++;
1585 current_thread = cur_env_tree;
1586 }
1587
1588 /*
1589 Finally, the threads are
1590 sorted by the sent date of the first message in the thread.
1591 Note that each message in a thread is a child (as opposed to a
1592 sibling) of the previous message.
1593 */
1594
1595#if 0
1596 if (comp_func != NULL) {
1597 r = mail_thread_sort(root, comp_func, FALSE);
1598 if (r != MAIL_NO_ERROR) {
1599 res = r;
1600 goto free;
1601 }
1602 }
1603#endif
1604
1605 if (comp_func == NULL)
1606 comp_func = mailthread_tree_timecomp;
1607
1608 r = mail_thread_sort(root, comp_func, FALSE);
1609 if (r != MAIL_NO_ERROR) {
1610 res = r;
1611 goto free;
1612 }
1613
1614 * result = root;
1615
1616 return MAIL_NO_ERROR;
1617
1618 free:
1619 mailmessage_tree_free_recursive(root);
1620 err:
1621 return res;
1622}
1623
1624
1625static int
1626mail_build_thread_none(char * default_from,
1627 struct mailmessage_list * env_list,
1628 struct mailmessage_tree ** result,
1629 int (* comp_func)(struct mailmessage_tree **,
1630 struct mailmessage_tree **))
1631{
1632 unsigned int i;
1633 carray * rootlist;
1634 struct mailmessage_tree * root;
1635 int res;
1636 int r;
1637
1638 root = mailmessage_tree_new(NULL, (time_t) -1, NULL);
1639 if (root == NULL) {
1640 res = MAIL_ERROR_MEMORY;
1641 goto err;
1642 }
1643 rootlist = root->node_children;
1644
1645 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1646 mailmessage * msg;
1647 struct mailmessage_tree * env_tree;
1648 char * base_subject;
1649 time_t date;
1650
1651 msg = carray_get(env_list->msg_tab, i);
1652
1653 if (msg == NULL)
1654 continue;
1655
1656 if (msg->msg_fields != NULL) {
1657
1658 date = get_date(msg);
1659
1660 env_tree = mailmessage_tree_new(NULL, date, msg);
1661 if (env_tree == NULL) {
1662 res = MAIL_ERROR_MEMORY;
1663 goto free;
1664 }
1665
1666 /* set parent */
1667 env_tree->node_parent = root;
1668 r = carray_add(rootlist, env_tree, NULL);
1669 if (r < 0) {
1670 mailmessage_tree_free(env_tree);
1671 res = MAIL_ERROR_MEMORY;
1672 goto free;
1673 }
1674
1675 r = get_extracted_subject(default_from, env_tree, &base_subject);
1676 switch (r) {
1677 case MAIL_NO_ERROR:
1678 env_tree->node_base_subject = base_subject;
1679 break;
1680
1681 case MAIL_ERROR_SUBJECT_NOT_FOUND:
1682 break;
1683
1684 default:
1685 res = r;
1686 goto free;
1687 }
1688 }
1689 }
1690
1691 if (comp_func == NULL)
1692 comp_func = mailthread_tree_timecomp;
1693
1694 r = mail_thread_sort(root, comp_func, FALSE);
1695 if (r != MAIL_NO_ERROR) {
1696 res = r;
1697 goto free;
1698 }
1699
1700 * result = root;
1701
1702 return MAIL_NO_ERROR;
1703
1704 free:
1705 mailmessage_tree_free_recursive(root);
1706 err:
1707 return res;
1708}
1709
1710
1711int mail_build_thread(int type, char * default_from,
1712 struct mailmessage_list * env_list,
1713 struct mailmessage_tree ** result,
1714 int (* comp_func)(struct mailmessage_tree **,
1715 struct mailmessage_tree **))
1716{
1717 unsigned int i;
1718
1719 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++)
1720 mailmessage_resolve_single_fields(carray_get(env_list->msg_tab, i));
1721
1722 switch (type) {
1723 case MAIL_THREAD_REFERENCES:
1724 return mail_build_thread_references(default_from,
1725 env_list, result, TRUE, comp_func);
1726
1727 case MAIL_THREAD_REFERENCES_NO_SUBJECT:
1728 return mail_build_thread_references(default_from,
1729 env_list, result, FALSE, comp_func);
1730
1731 case MAIL_THREAD_ORDEREDSUBJECT:
1732 return mail_build_thread_orderedsubject(default_from,
1733 env_list, result, comp_func);
1734
1735 case MAIL_THREAD_NONE:
1736 return mail_build_thread_none(default_from,
1737 env_list, result, comp_func);
1738
1739 default:
1740 return MAIL_ERROR_NOT_IMPLEMENTED;
1741 }
1742}
diff --git a/libetpan/src/driver/tools/mailthread.h b/libetpan/src/driver/tools/mailthread.h
new file mode 100644
index 0000000..fa2f4bc
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread.h
@@ -0,0 +1,108 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_H
37
38#define MAILTHREAD_H
39
40#include <libetpan/mailthread_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/*
47 mail_build_thread constructs a tree with the message using the
48 given style.
49
50 @param type is the type of threading to apply, the value can be
51 MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT,
52 MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE,
53
54 @param default_from is the default charset to use whenever the
55 subject is not tagged with a charset. "US-ASCII" can be used
56 if you don't know what to use.
57
58 @param env_list is the message list (with header fields fetched)
59 to use to build the message tree.
60
61 @param result * result) will contain the resulting message tree.
62
63 @param if comp_func is NULL, no sorting algorithm is used.
64
65 @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned
66 on error
67*/
68
69int mail_build_thread(int type, char * default_from,
70 struct mailmessage_list * env_list,
71 struct mailmessage_tree ** result,
72 int (* comp_func)(struct mailmessage_tree **,
73 struct mailmessage_tree **));
74
75/*
76 mail_thread_sort sort the messages in the message tree, using the
77 given sort function.
78
79 @param tree is the message tree to sort.
80
81 @param comp_func is the sort function to use (this is the same kind of
82 functions than those used for qsort()). mailthread_tree_timecomp can be
83 used for default sort.
84
85 @param sort_sub if this value is 0, only the children of the root message
86 are sorted.
87*/
88
89int mail_thread_sort(struct mailmessage_tree * tree,
90 int (* comp_func)(struct mailmessage_tree **,
91 struct mailmessage_tree **),
92 int sort_sub);
93
94/*
95 mailthread_tree_timecomp is the default sort function.
96
97 The message are compared by date, then by message numbers.
98 The tree are given in (* ptree1) and (* ptree2).
99*/
100
101int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1,
102 struct mailmessage_tree ** ptree2);
103
104#ifdef __cplusplus
105}
106#endif
107
108#endif
diff --git a/libetpan/src/driver/tools/mailthread_types.c b/libetpan/src/driver/tools/mailthread_types.c
new file mode 100644
index 0000000..dc2a4ca
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread_types.c
@@ -0,0 +1,90 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailthread_types.h"
37
38#include "mail.h"
39#include <stdlib.h>
40
41struct mailmessage_tree *
42mailmessage_tree_new(char * node_msgid, time_t node_date,
43 mailmessage * node_msg)
44{
45 struct mailmessage_tree * tree;
46 carray * array;
47
48 array = carray_new(16);
49 if (array == NULL)
50 return NULL;
51
52 tree = malloc(sizeof(* tree));
53 tree->node_parent = NULL;
54 tree->node_date = node_date;
55 tree->node_msgid = node_msgid;
56 tree->node_msg = node_msg;
57 tree->node_children = array;
58 tree->node_base_subject = NULL;
59 tree->node_is_reply = FALSE;
60
61 return tree;
62}
63
64void mailmessage_tree_free(struct mailmessage_tree * tree)
65{
66 if (tree->node_base_subject != NULL)
67 free(tree->node_base_subject);
68
69 if (tree->node_children != NULL)
70 carray_free(tree->node_children);
71 if (tree->node_msgid != NULL)
72 free(tree->node_msgid);
73
74 free(tree);
75}
76
77void mailmessage_tree_free_recursive(struct mailmessage_tree * tree)
78{
79 unsigned int i;
80
81 for(i = 0 ; i < carray_count(tree->node_children) ; i++) {
82 struct mailmessage_tree * child;
83
84 child = carray_get(tree->node_children, i);
85
86 mailmessage_tree_free_recursive(child);
87 }
88
89 mailmessage_tree_free(tree);
90}
diff --git a/libetpan/src/driver/tools/mailthread_types.h b/libetpan/src/driver/tools/mailthread_types.h
new file mode 100644
index 0000000..3325904
--- a/dev/null
+++ b/libetpan/src/driver/tools/mailthread_types.h
@@ -0,0 +1,64 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILTHREAD_TYPES_H
37
38#define MAILTHREAD_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/maildriver_types.h>
45#include <libetpan/mailmessage_types.h>
46
47/*
48 This is the type of tree construction to apply.
49*/
50
51enum {
52 MAIL_THREAD_REFERENCES, /* this is threading using
53 References fields only) */
54 MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References
55 fields, then subject */
56 MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */
57 MAIL_THREAD_NONE, /* no thread */
58};
59
60#ifdef __cplusplus
61}
62#endif
63
64#endif
diff --git a/libetpan/src/engine/mailengine.c b/libetpan/src/engine/mailengine.c
new file mode 100644
index 0000000..be4df38
--- a/dev/null
+++ b/libetpan/src/engine/mailengine.c
@@ -0,0 +1,1636 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailengine.h"
37
38#ifndef CONFIG_H
39#define CONFIG_H
40#include "config.h"
41#endif
42
43#include "mailfolder.h"
44#include "maildriver.h"
45#include "imapdriver_cached.h"
46#include "mailstorage.h"
47#include "imapdriver_cached_message.h"
48#include <stdlib.h>
49#include "mailprivacy.h"
50#ifdef LIBETPAN_REENTRANT
51#include <pthread.h>
52#endif
53#include <string.h>
54
55/* ************************************************************* */
56/* Message finder */
57
58#if 0
59struct message_folder_finder {
60#ifdef LIBETPAN_REENTRANT
61 pthread_mutex_t lock;
62#endif
63
64 /* msg => folder */
65 chash * message_hash;
66};
67
68static int message_folder_finder_init(struct message_folder_finder * finder)
69{
70 int r;
71
72#ifdef LIBETPAN_REENTRANT
73 r = pthread_mutex_init(&finder->lock, NULL);
74 if (r != 0)
75 return MAIL_ERROR_MEMORY;
76#endif
77
78 finder->message_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
79 if (finder->message_hash == NULL)
80 return MAIL_ERROR_MEMORY;
81
82 return MAIL_NO_ERROR;
83}
84
85static void message_folder_finder_done(struct message_folder_finder * finder)
86{
87 chash_free(finder->message_hash);
88#ifdef LIBETPAN_REENTRANT
89 pthread_mutex_destroy(&finder->lock);
90#endif
91}
92
93static struct mailfolder *
94message_folder_finder_lookup(struct message_folder_finder * finder,
95 mailmessage * msg)
96{
97 int r;
98 chashdatum key;
99 chashdatum data;
100 struct mailfolder * folder;
101
102 key.data = &msg;
103 key.len = sizeof(msg);
104#ifdef LIBETPAN_REENTRANT
105 pthread_mutex_lock(&finder->lock);
106#endif
107 r = chash_get(finder->message_hash, &key, &data);
108#ifdef LIBETPAN_REENTRANT
109 pthread_mutex_unlock(&finder->lock);
110#endif
111 if (r < 0)
112 return NULL;
113
114 folder = data.data;
115
116 return folder;
117}
118
119static inline int
120message_folder_finder_store_no_lock(struct message_folder_finder * finder,
121 mailmessage * msg, struct mailfolder * folder)
122{
123 int r;
124 chashdatum key;
125 chashdatum data;
126
127 key.data = &msg;
128 key.len = sizeof(msg);
129 data.data = folder;
130 data.len = 0;
131 r = chash_set(finder->message_hash, &key, &data, NULL);
132 if (r < 0)
133 return MAIL_ERROR_MEMORY;
134
135 return MAIL_NO_ERROR;
136}
137
138static int
139message_folder_finder_store(struct message_folder_finder * finder,
140 mailmessage * msg, struct mailfolder * folder)
141{
142 int r;
143
144#ifdef LIBETPAN_REENTRANT
145 pthread_mutex_lock(&finder->lock);
146#endif
147 r = message_folder_finder_store_no_lock(finder, msg, folder);
148#ifdef LIBETPAN_REENTRANT
149 pthread_mutex_unlock(&finder->lock);
150#endif
151
152 return r;
153}
154
155static inline void
156message_folder_finder_delete_no_lock(struct message_folder_finder * finder,
157 mailmessage * msg)
158{
159 chashdatum key;
160
161 key.data = &msg;
162 key.len = sizeof(msg);
163 chash_delete(finder->message_hash, &key, NULL);
164}
165
166static void
167message_folder_finder_delete(struct message_folder_finder * finder,
168 mailmessage * msg)
169{
170#ifdef LIBETPAN_REENTRANT
171 pthread_mutex_lock(&finder->lock);
172#endif
173 message_folder_finder_delete_no_lock(finder, msg);
174#ifdef LIBETPAN_REENTRANT
175 pthread_mutex_unlock(&finder->lock);
176#endif
177}
178#endif
179
180/* ************************************************************* */
181/* Message ref info */
182
183struct message_ref_elt {
184 mailmessage * msg;
185 int ref_count;
186 int mime_ref_count;
187 struct mailfolder * folder;
188 int lost;
189};
190
191static struct message_ref_elt *
192message_ref_elt_new(struct mailfolder * folder, mailmessage * msg)
193{
194 struct message_ref_elt * ref;
195
196 ref = malloc(sizeof(* ref));
197 if (ref == NULL)
198 return NULL;
199
200 ref->msg = msg;
201 ref->ref_count = 0;
202 ref->mime_ref_count = 0;
203 ref->folder = folder;
204 ref->lost = 0;
205
206 return ref;
207}
208
209static void message_ref_elt_free(struct message_ref_elt * ref_elt)
210{
211 free(ref_elt);
212}
213
214static inline int message_ref(struct message_ref_elt * ref_elt)
215{
216 ref_elt->ref_count ++;
217
218 return ref_elt->ref_count;
219}
220
221static inline int message_unref(struct message_ref_elt * ref_elt)
222{
223 ref_elt->ref_count --;
224
225 return ref_elt->ref_count;
226}
227
228
229static inline int message_mime_ref(struct mailprivacy * privacy,
230 struct message_ref_elt * ref_elt)
231{
232 int r;
233
234 if (ref_elt->mime_ref_count == 0) {
235 struct mailmime * mime;
236
237 r = mailprivacy_msg_get_bodystructure(privacy, ref_elt->msg, &mime);
238 if (r != MAIL_NO_ERROR)
239 return -r;
240 }
241
242 message_ref(ref_elt);
243
244 ref_elt->mime_ref_count ++;
245
246 return ref_elt->mime_ref_count;
247}
248
249static inline int message_mime_unref(struct mailprivacy * privacy,
250 struct message_ref_elt * ref_elt)
251{
252 message_unref(ref_elt);
253
254 ref_elt->mime_ref_count --;
255
256 if (ref_elt->mime_ref_count == 0)
257 mailprivacy_msg_flush(privacy, ref_elt->msg);
258
259 return ref_elt->mime_ref_count;
260}
261
262
263/* ************************************************************* */
264/* Folder ref info */
265
266struct folder_ref_info {
267 struct mailfolder * folder;
268#if 0
269 struct message_folder_finder * msg_folder_finder;
270#endif
271
272 /* msg => msg_ref_info */
273 chash * msg_hash;
274
275 /* uid => msg */
276 chash * uid_hash;
277
278 int lost_session;
279};
280
281static struct folder_ref_info *
282folder_ref_info_new(struct mailfolder * folder
283 /*, struct message_folder_finder * msg_folder_finder */)
284{
285 struct folder_ref_info * ref_info;
286
287 ref_info = malloc(sizeof(* ref_info));
288 if (ref_info == NULL)
289 goto err;
290
291 ref_info->folder = folder;
292#if 0
293 ref_info->msg_folder_finder = msg_folder_finder;
294#endif
295
296 ref_info->msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
297 if (ref_info->msg_hash == NULL)
298 goto free;
299
300 ref_info->uid_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE);
301 if (ref_info->uid_hash == NULL)
302 goto free_msg_hash;
303
304 ref_info->lost_session = 1;
305
306 return ref_info;
307
308 free_msg_hash:
309 chash_free(ref_info->msg_hash);
310 free:
311 free(ref_info);
312 err:
313 return NULL;
314}
315
316static void folder_ref_info_free(struct folder_ref_info * ref_info)
317{
318 chash_free(ref_info->uid_hash);
319 chash_free(ref_info->msg_hash);
320 free(ref_info);
321}
322
323static struct message_ref_elt *
324folder_info_get_msg_ref(struct folder_ref_info * ref_info, mailmessage * msg)
325{
326 chashdatum key;
327 chashdatum data;
328 struct message_ref_elt * ref_elt;
329 int r;
330
331 key.data = &msg;
332 key.len = sizeof(msg);
333 r = chash_get(ref_info->msg_hash, &key, &data);
334 if (r < 0)
335 return NULL;
336
337 ref_elt = data.data;
338
339 return ref_elt;
340}
341
342static mailmessage *
343folder_info_get_msg_by_uid(struct folder_ref_info * ref_info,
344 char * uid)
345{
346 chashdatum key;
347 chashdatum data;
348 mailmessage * msg;
349 int r;
350
351 key.data = uid;
352 key.len = strlen(uid);
353 r = chash_get(ref_info->uid_hash, &key, &data);
354 if (r < 0)
355 return NULL;
356
357 msg = data.data;
358
359 return msg;
360}
361
362static int folder_message_ref(struct folder_ref_info * ref_info,
363 mailmessage * msg)
364{
365 struct message_ref_elt * msg_ref;
366
367 msg_ref = folder_info_get_msg_ref(ref_info, msg);
368 return message_ref(msg_ref);
369}
370
371static void folder_message_remove(struct folder_ref_info * ref_info,
372 mailmessage * msg);
373
374#ifdef DEBUG_ENGINE
375#include "etpan-app.h"
376
377void * engine_app = NULL;
378#endif
379
380static int folder_message_unref(struct folder_ref_info * ref_info,
381 mailmessage * msg)
382{
383 struct message_ref_elt * msg_ref;
384 int count;
385
386 msg_ref = folder_info_get_msg_ref(ref_info, msg);
387
388 if (msg_ref->ref_count == 0) {
389#ifdef ETPAN_APP_DEBUG
390 ETPAN_APP_DEBUG((engine_app, "** BUG detected negative ref count !"));
391#endif
392 }
393
394 count = message_unref(msg_ref);
395 if (count == 0) {
396 folder_message_remove(ref_info, msg);
397 mailmessage_free(msg);
398 }
399
400 return count;
401}
402
403static int folder_message_mime_ref(struct mailprivacy * privacy,
404 struct folder_ref_info * ref_info,
405 mailmessage * msg)
406{
407 struct message_ref_elt * msg_ref;
408
409 msg_ref = folder_info_get_msg_ref(ref_info, msg);
410
411 return message_mime_ref(privacy, msg_ref);
412}
413
414static int folder_message_mime_unref(struct mailprivacy * privacy,
415 struct folder_ref_info * ref_info,
416 mailmessage * msg)
417{
418 struct message_ref_elt * msg_ref;
419
420 msg_ref = folder_info_get_msg_ref(ref_info, msg);
421 return message_mime_unref(privacy, msg_ref);
422}
423
424static int folder_message_add(struct folder_ref_info * ref_info,
425 mailmessage * msg)
426{
427 chashdatum key;
428 chashdatum data;
429 struct message_ref_elt * msg_ref;
430 int r;
431
432 /*
433 r = message_folder_finder_store(ref_info->msg_folder_finder,
434 msg, ref_info->folder);
435 if (r != MAIL_NO_ERROR)
436 goto err;
437 */
438
439 msg_ref = message_ref_elt_new(ref_info->folder, msg);
440 if (msg_ref == NULL)
441 goto msg_folder_remove;
442
443 key.data = &msg;
444 key.len = sizeof(msg);
445 data.data = msg_ref;
446 data.len = 0;
447
448 r = chash_set(ref_info->msg_hash, &key, &data, NULL);
449 if (r < 0)
450 goto free_msg_ref;
451
452 if (msg->msg_uid != NULL) {
453 key.data = msg->msg_uid;
454 key.len = strlen(msg->msg_uid);
455 data.data = msg;
456 data.len = 0;
457
458 r = chash_set(ref_info->uid_hash, &key, &data, NULL);
459 if (r < 0)
460 goto remove_msg_ref;
461 }
462
463 return MAIL_NO_ERROR;
464
465 remove_msg_ref:
466 key.data = &msg;
467 key.len = sizeof(msg);
468 chash_delete(ref_info->msg_hash, &key, NULL);
469 free_msg_ref:
470 message_ref_elt_free(msg_ref);
471 msg_folder_remove:
472 /*
473 message_folder_finder_delete(ref_info->msg_folder_finder, msg);
474 */
475 err:
476 return MAIL_ERROR_MEMORY;
477}
478
479
480static void folder_message_remove(struct folder_ref_info * ref_info,
481 mailmessage * msg)
482{
483 chashdatum key;
484 struct message_ref_elt * msg_ref;
485
486 if (msg->msg_uid != NULL) {
487 key.data = msg->msg_uid;
488 key.len = strlen(msg->msg_uid);
489
490 chash_delete(ref_info->uid_hash, &key, NULL);
491 }
492
493 msg_ref = folder_info_get_msg_ref(ref_info, msg);
494 message_ref_elt_free(msg_ref);
495
496 key.data = &msg;
497 key.len = sizeof(msg);
498
499 chash_delete(ref_info->msg_hash, &key, NULL);
500
501 /*
502 message_folder_finder_delete(ref_info->msg_folder_finder, msg);
503 */
504}
505
506
507static int folder_update_msg_list(struct folder_ref_info * ref_info,
508 struct mailmessage_list ** p_new_msg_list,
509 struct mailmessage_list ** p_lost_msg_list)
510{
511 int r;
512 int res;
513 struct mailmessage_list * new_env_list;
514 unsigned int i;
515 carray * lost_msg_tab;
516 struct mailmessage_list * lost_msg_list;
517 unsigned int free_start_index;
518 chashiter * iter;
519 unsigned int lost_count;
520
521 r = mailfolder_get_messages_list(ref_info->folder, &new_env_list);
522 if (r != MAIL_NO_ERROR) {
523 res = r;
524 goto err;
525 }
526
527 for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ;
528 iter = chash_next(ref_info->msg_hash, iter)) {
529 struct message_ref_elt * msg_ref;
530 chashdatum data;
531
532 chash_value(iter, &data);
533 msg_ref = data.data;
534 msg_ref->lost = 1;
535 }
536
537 lost_count = chash_count(ref_info->msg_hash);
538
539 for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) {
540 mailmessage * msg;
541 mailmessage * old_msg;
542
543 msg = carray_get(new_env_list->msg_tab, i);
544
545 if (msg->msg_uid == NULL)
546 continue;
547
548 old_msg = folder_info_get_msg_by_uid(ref_info, msg->msg_uid);
549 if (old_msg != NULL) {
550 struct message_ref_elt * msg_ref;
551
552 /* replace old message */
553 old_msg->msg_index = msg->msg_index;
554 carray_set(new_env_list->msg_tab, i, old_msg);
555 mailmessage_free(msg);
556
557 msg_ref = folder_info_get_msg_ref(ref_info, old_msg);
558 msg_ref->lost = 0;
559 lost_count --;
560 }
561 else {
562 /* set new message */
563 r = folder_message_add(ref_info, msg);
564 if (r != MAIL_NO_ERROR) {
565 free_start_index = i;
566 res = r;
567 goto free_remaining;
568 }
569 }
570 }
571
572 /* build the table of lost messages */
573 lost_msg_tab = carray_new(lost_count);
574 if (lost_msg_tab == NULL) {
575 res = MAIL_ERROR_MEMORY;
576 goto free_env_list;
577 }
578
579 carray_set_size(lost_msg_tab, lost_count);
580
581 i = 0;
582 for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ;
583 iter = chash_next(ref_info->msg_hash, iter)) {
584 struct message_ref_elt * msg_ref;
585 chashdatum key;
586 chashdatum value;
587 mailmessage * msg;
588
589 chash_key(iter, &key);
590 memcpy(&msg, key.data, sizeof(msg));
591
592 chash_value(iter, &value);
593 msg_ref = value.data;
594 if (msg_ref->lost) {
595 carray_set(lost_msg_tab, i, msg);
596 i ++;
597 }
598 }
599
600 lost_msg_list = mailmessage_list_new(lost_msg_tab);
601 if (lost_msg_list == NULL) {
602 res = MAIL_ERROR_MEMORY;
603 goto free_lost_msg_tab;
604 }
605
606 /* reference messages */
607 for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) {
608 mailmessage * msg;
609
610 msg = carray_get(new_env_list->msg_tab, i);
611 folder_message_ref(ref_info, msg);
612 }
613
614 * p_new_msg_list = new_env_list;
615 * p_lost_msg_list = lost_msg_list;
616
617 return MAIL_NO_ERROR;
618
619 free_lost_msg_tab:
620 carray_free(lost_msg_tab);
621 free_env_list:
622 for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) {
623 mailmessage * msg;
624 struct message_ref_elt * msg_ref;
625
626 msg = carray_get(new_env_list->msg_tab, i);
627 msg_ref = folder_info_get_msg_ref(ref_info, msg);
628 if (msg_ref != NULL) {
629 if (msg_ref->ref_count == 0)
630 folder_message_remove(ref_info, msg);
631 }
632 }
633 carray_set_size(new_env_list->msg_tab, 0);
634 mailmessage_list_free(new_env_list);
635 goto err;
636 free_remaining:
637 for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) {
638 mailmessage * msg;
639 struct message_ref_elt * msg_ref;
640
641 msg = carray_get(new_env_list->msg_tab, i);
642 msg_ref = folder_info_get_msg_ref(ref_info, msg);
643 if (msg_ref != NULL) {
644 if (msg_ref->ref_count == 0)
645 folder_message_remove(ref_info, msg);
646 }
647 }
648 for(i = free_start_index ; i < carray_count(new_env_list->msg_tab) ; i ++) {
649 mailmessage * msg;
650
651 msg = carray_get(new_env_list->msg_tab, i);
652 mailmessage_free(msg);
653 }
654 carray_set_size(new_env_list->msg_tab, 0);
655 mailmessage_list_free(new_env_list);
656 err:
657 return res;
658}
659
660/*
661 folder_fetch_env_list()
662*/
663
664static int folder_fetch_env_list(struct folder_ref_info * ref_info,
665 struct mailmessage_list * msg_list)
666{
667 return mailfolder_get_envelopes_list(ref_info->folder, msg_list);
668}
669
670static void folder_free_msg_list(struct folder_ref_info * ref_info,
671 struct mailmessage_list * env_list)
672{
673 unsigned int i;
674
675 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
676 mailmessage * msg;
677 int count;
678
679 msg = carray_get(env_list->msg_tab, i);
680
681 count = folder_message_unref(ref_info, msg);
682 }
683 carray_set_size(env_list->msg_tab, 0);
684 mailmessage_list_free(env_list);
685}
686
687
688/* ************************************************************* */
689/* Storage ref info */
690
691struct storage_ref_info {
692 struct mailstorage * storage;
693#if 0
694 struct message_folder_finder * msg_folder_finder;
695#endif
696
697#if 0
698 /* msg => folder */
699 chash * msg_ref;
700#endif
701
702 /* folder => folder_ref_info */
703 chash * folder_ref_info;
704};
705
706static struct storage_ref_info *
707storage_ref_info_new(struct mailstorage * storage
708 /*, struct message_folder_finder * msg_folder_finder */)
709{
710 struct storage_ref_info * ref_info;
711
712 ref_info = malloc(sizeof(* ref_info));
713 if (ref_info == NULL)
714 goto err;
715
716 ref_info->storage = storage;
717#if 0
718 ref_info->msg_folder_finder = msg_folder_finder;
719#endif
720
721 ref_info->folder_ref_info = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
722 if (ref_info->folder_ref_info == NULL)
723 goto free;
724
725 return ref_info;
726
727 free:
728 free(ref_info);
729 err:
730 return NULL;
731}
732
733static void storage_ref_info_free(struct storage_ref_info * ref_info)
734{
735#if 0
736 chash_free(ref_info->msg_ref);
737#endif
738 chash_free(ref_info->folder_ref_info);
739 free(ref_info);
740}
741
742
743static struct folder_ref_info *
744storage_get_folder_ref(struct storage_ref_info * ref_info,
745 struct mailfolder * folder)
746{
747 struct folder_ref_info * folder_ref;
748 chashdatum key;
749 chashdatum value;
750 int r;
751
752 key.data = &folder;
753 key.len = sizeof(folder);
754 r = chash_get(ref_info->folder_ref_info, &key, &value);
755 if (r < 0)
756 return NULL;
757
758 folder_ref = value.data;
759
760 return folder_ref;
761}
762
763static struct folder_ref_info *
764storage_folder_add_ref(struct storage_ref_info * ref_info,
765 struct mailfolder * folder)
766{
767 struct folder_ref_info * folder_ref;
768 chashdatum key;
769 chashdatum value;
770 int r;
771
772 folder_ref = folder_ref_info_new(folder /*, ref_info->msg_folder_finder */);
773 if (folder_ref == NULL)
774 goto err;
775
776 key.data = &folder;
777 key.len = sizeof(folder);
778 value.data = folder_ref;
779 value.len = 0;
780 r = chash_set(ref_info->folder_ref_info, &key, &value, NULL);
781 if (r < 0)
782 goto free;
783
784 return folder_ref;
785
786 free:
787 folder_ref_info_free(folder_ref);
788 err:
789 return NULL;
790}
791
792
793static void storage_folder_remove_ref(struct storage_ref_info * ref_info,
794 struct mailfolder * folder)
795{
796 struct folder_ref_info * folder_ref;
797 chashdatum key;
798 chashdatum value;
799 int r;
800
801 key.data = &folder;
802 key.len = sizeof(folder);
803 r = chash_get(ref_info->folder_ref_info, &key, &value);
804 if (r < 0)
805 return;
806
807 folder_ref = value.data;
808
809 if (folder_ref == NULL)
810 return;
811
812 folder_ref_info_free(folder_ref);
813
814 chash_delete(ref_info->folder_ref_info, &key, &value);
815}
816
817static int storage_folder_get_msg_list(struct storage_ref_info * ref_info,
818 struct mailfolder * folder,
819 struct mailmessage_list ** p_new_msg_list,
820 struct mailmessage_list ** p_lost_msg_list)
821{
822 struct folder_ref_info * folder_ref_info;
823
824 folder_ref_info = storage_get_folder_ref(ref_info, folder);
825 if (folder_ref_info == NULL)
826 return MAIL_ERROR_INVAL;
827
828 return folder_update_msg_list(folder_ref_info,
829 p_new_msg_list, p_lost_msg_list);
830}
831
832static int storage_folder_fetch_env_list(struct storage_ref_info * ref_info,
833 struct mailfolder * folder,
834 struct mailmessage_list * msg_list)
835{
836 struct folder_ref_info * folder_ref_info;
837
838 folder_ref_info = storage_get_folder_ref(ref_info, folder);
839 if (folder_ref_info == NULL)
840 return MAIL_ERROR_INVAL;
841
842 return folder_fetch_env_list(folder_ref_info, msg_list);
843}
844
845static void
846storage_folder_free_msg_list(struct storage_ref_info * ref_info,
847 struct mailfolder * folder,
848 struct mailmessage_list * env_list)
849{
850 struct folder_ref_info * folder_ref_info;
851
852 folder_ref_info = storage_get_folder_ref(ref_info, folder);
853
854 folder_free_msg_list(folder_ref_info, env_list);
855}
856
857
858/* connection and disconnection */
859
860static void
861folder_restore_session(struct folder_ref_info * ref_info)
862{
863 chashiter * iter;
864 mailsession * session;
865
866 session = ref_info->folder->fld_session;
867
868 for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ;
869 iter = chash_next(ref_info->msg_hash, iter)) {
870 chashdatum key;
871 mailmessage * msg;
872
873 chash_key(iter, &key);
874 memcpy(&msg, key.data, sizeof(msg));
875 msg->msg_session = session;
876
877 if (msg->msg_driver == imap_cached_message_driver) {
878 struct imap_cached_session_state_data * imap_cached_data;
879 mailmessage * ancestor_msg;
880
881 imap_cached_data = ref_info->folder->fld_session->sess_data;
882 ancestor_msg = msg->msg_data;
883 ancestor_msg->msg_session = imap_cached_data->imap_ancestor;
884 }
885 }
886}
887
888static void
889storage_restore_message_session(struct storage_ref_info * ref_info)
890{
891 chashiter * iter;
892
893 for(iter = chash_begin(ref_info->folder_ref_info) ; iter != NULL ;
894 iter = chash_next(ref_info->folder_ref_info, iter)) {
895 chashdatum data;
896 struct folder_ref_info * folder_ref_info;
897
898 chash_value(iter, &data);
899 folder_ref_info = data.data;
900 if (folder_ref_info->lost_session) {
901 if (folder_ref_info->folder->fld_session != NULL) {
902 /* restore folder session */
903 folder_restore_session(folder_ref_info);
904
905 folder_ref_info->lost_session = 0;
906 }
907 }
908 }
909}
910
911
912static int do_storage_connect(struct storage_ref_info * ref_info)
913{
914 int r;
915
916 r = mailstorage_connect(ref_info->storage);
917 if (r != MAIL_NO_ERROR)
918 return r;
919
920 return MAIL_NO_ERROR;
921}
922
923static void do_storage_disconnect(struct storage_ref_info * ref_info)
924{
925 clistiter * cur;
926
927 /* storage is disconnected, session is lost */
928 for(cur = clist_begin(ref_info->storage->sto_shared_folders) ; cur != NULL ;
929 cur = clist_next(cur)) {
930 struct folder_ref_info * folder_ref_info;
931 struct mailfolder * folder;
932
933 folder = clist_content(cur);
934 /* folder is disconnected (in storage), session is lost */
935
936 folder_ref_info = storage_get_folder_ref(ref_info, folder);
937 folder_ref_info->lost_session = 1;
938 }
939
940 /* storage is disconnected */
941 mailstorage_disconnect(ref_info->storage);
942}
943
944
945
946static int folder_connect(struct storage_ref_info * ref_info,
947 struct mailfolder * folder)
948{
949 int r;
950 struct folder_ref_info * folder_ref_info;
951
952 r = do_storage_connect(ref_info);
953 if (r != MAIL_NO_ERROR)
954 return r;
955
956 r = mailfolder_connect(folder);
957 if (r != MAIL_NO_ERROR)
958 return r;
959
960 folder_ref_info = storage_get_folder_ref(ref_info, folder);
961
962 return MAIL_NO_ERROR;
963}
964
965
966static void folder_disconnect(struct storage_ref_info * ref_info,
967 struct mailfolder * folder)
968{
969 struct folder_ref_info * folder_ref_info;
970
971 folder_ref_info = storage_get_folder_ref(ref_info, folder);
972
973 /* folder is disconnected, session is lost */
974 folder_ref_info->lost_session = 1;
975 mailfolder_disconnect(folder);
976
977 if (folder->fld_shared_session)
978 do_storage_disconnect(ref_info);
979}
980
981
982static int storage_folder_connect(struct storage_ref_info * ref_info,
983 struct mailfolder * folder)
984{
985 int r;
986 int res;
987 struct folder_ref_info * folder_ref_info;
988
989 folder_ref_info = storage_get_folder_ref(ref_info, folder);
990 if (folder_ref_info == NULL) {
991 folder_ref_info = storage_folder_add_ref(ref_info, folder);
992 if (folder_ref_info == NULL)
993 return MAIL_ERROR_MEMORY;
994 }
995
996 /* connect folder */
997
998 r = folder_connect(ref_info, folder);
999 if (r == MAIL_ERROR_STREAM) {
1000 /* properly handles disconnection */
1001
1002 /* reconnect */
1003 folder_disconnect(ref_info, folder);
1004 r = folder_connect(ref_info, folder);
1005 }
1006
1007 if (r != MAIL_NO_ERROR) {
1008 res = r;
1009 goto err;
1010 }
1011
1012 /* test folder connection */
1013 r = mailfolder_noop(folder);
1014 if (r == MAIL_ERROR_STREAM) {
1015 /* reconnect */
1016 folder_disconnect(ref_info, folder);
1017 r = folder_connect(ref_info, folder);
1018 }
1019
1020 if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) {
1021 res = r;
1022 goto disconnect;
1023 }
1024
1025 storage_restore_message_session(ref_info);
1026
1027 return MAIL_NO_ERROR;
1028
1029 disconnect:
1030 folder_disconnect(ref_info, folder);
1031 err:
1032 return res;
1033}
1034
1035static void storage_folder_disconnect(struct storage_ref_info * ref_info,
1036 struct mailfolder * folder)
1037{
1038 mailfolder_disconnect(folder);
1039 storage_folder_remove_ref(ref_info, folder);
1040}
1041
1042static int storage_connect(struct storage_ref_info * ref_info)
1043{
1044 int r;
1045 int res;
1046
1047 /* connect storage */
1048
1049 /* properly handles disconnection */
1050 r = do_storage_connect(ref_info);
1051 if (r == MAIL_ERROR_STREAM) {
1052 /* reconnect storage */
1053 do_storage_disconnect(ref_info);
1054 r = do_storage_connect(ref_info);
1055 }
1056
1057 if (r != MAIL_NO_ERROR) {
1058 res = r;
1059 goto disconnect;
1060 }
1061
1062 /* test storage connection */
1063
1064 r = mailsession_noop(ref_info->storage->sto_session);
1065 if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) {
1066 /* properly handles disconnection */
1067
1068 /* reconnect storage */
1069 do_storage_disconnect(ref_info);
1070 r = do_storage_connect(ref_info);
1071 }
1072
1073 if (r != MAIL_NO_ERROR) {
1074 res = r;
1075 goto disconnect;
1076 }
1077
1078 storage_restore_message_session(ref_info);
1079
1080 return MAIL_NO_ERROR;
1081
1082 disconnect:
1083 do_storage_disconnect(ref_info);
1084 return res;
1085}
1086
1087
1088static void storage_disconnect(struct storage_ref_info * ref_info)
1089{
1090 chashiter * iter;
1091
1092 /* disconnect folders */
1093 while ((iter = chash_begin(ref_info->folder_ref_info)) != NULL) {
1094 chashdatum key;
1095 struct mailfolder * folder;
1096
1097 chash_key(iter, &key);
1098 memcpy(&folder, key.data, sizeof(folder));
1099
1100 storage_folder_disconnect(ref_info, folder);
1101 }
1102
1103 /* disconnect storage */
1104 do_storage_disconnect(ref_info);
1105}
1106
1107
1108/* ************************************************************* */
1109/* interface for mailengine */
1110
1111struct mailengine {
1112 struct mailprivacy * privacy;
1113
1114#ifdef LIBETPAN_REENTRANT
1115 pthread_mutex_t storage_hash_lock;
1116#endif
1117 /* storage => storage_ref_info */
1118 chash * storage_hash;
1119
1120#if 0
1121 struct message_folder_finder msg_folder_finder;
1122#endif
1123};
1124
1125static struct storage_ref_info *
1126get_storage_ref_info(struct mailengine * engine,
1127 struct mailstorage * storage)
1128{
1129 chashdatum key;
1130 chashdatum data;
1131 int r;
1132 struct storage_ref_info * ref_info;
1133
1134 key.data = &storage;
1135 key.len = sizeof(storage);
1136#ifdef LIBETPAN_REENTRANT
1137 pthread_mutex_lock(&engine->storage_hash_lock);
1138#endif
1139 r = chash_get(engine->storage_hash, &key, &data);
1140#ifdef LIBETPAN_REENTRANT
1141 pthread_mutex_unlock(&engine->storage_hash_lock);
1142#endif
1143 if (r < 0)
1144 return NULL;
1145
1146 ref_info = data.data;
1147
1148 return ref_info;
1149}
1150
1151static struct storage_ref_info *
1152add_storage_ref_info(struct mailengine * engine,
1153 struct mailstorage * storage)
1154{
1155 chashdatum key;
1156 chashdatum data;
1157 int r;
1158 struct storage_ref_info * ref_info;
1159
1160 ref_info = storage_ref_info_new(storage
1161 /* , &engine->msg_folder_finder */);
1162 if (ref_info == NULL)
1163 goto err;
1164
1165 key.data = &storage;
1166 key.len = sizeof(storage);
1167 data.data = ref_info;
1168 data.len = 0;
1169
1170#ifdef LIBETPAN_REENTRANT
1171 pthread_mutex_lock(&engine->storage_hash_lock);
1172#endif
1173 r = chash_set(engine->storage_hash, &key, &data, NULL);
1174#ifdef LIBETPAN_REENTRANT
1175 pthread_mutex_unlock(&engine->storage_hash_lock);
1176#endif
1177 if (r < 0)
1178 goto free;
1179
1180 ref_info = data.data;
1181
1182 return ref_info;
1183
1184 free:
1185 storage_ref_info_free(ref_info);
1186 err:
1187 return NULL;
1188}
1189
1190static void
1191remove_storage_ref_info(struct mailengine * engine,
1192 struct mailstorage * storage)
1193{
1194 chashdatum key;
1195 chashdatum data;
1196 struct storage_ref_info * ref_info;
1197
1198 key.data = &storage;
1199 key.len = sizeof(storage);
1200
1201#ifdef LIBETPAN_REENTRANT
1202 pthread_mutex_lock(&engine->storage_hash_lock);
1203#endif
1204
1205 chash_get(engine->storage_hash, &key, &data);
1206 ref_info = data.data;
1207
1208 if (ref_info != NULL) {
1209 storage_ref_info_free(ref_info);
1210
1211 chash_delete(engine->storage_hash, &key, NULL);
1212 }
1213
1214#ifdef LIBETPAN_REENTRANT
1215 pthread_mutex_unlock(&engine->storage_hash_lock);
1216#endif
1217}
1218
1219struct mailengine *
1220libetpan_engine_new(struct mailprivacy * privacy)
1221{
1222 struct mailengine * engine;
1223 int r;
1224
1225 engine = malloc(sizeof(* engine));
1226 if (engine == NULL)
1227 goto err;
1228
1229 engine->privacy = privacy;
1230
1231#if 0
1232 r = message_folder_finder_init(&engine->msg_folder_finder);
1233 if (r != MAIL_NO_ERROR)
1234 goto free;
1235#endif
1236
1237#ifdef LIBETPAN_REENTRANT
1238 r = pthread_mutex_init(&engine->storage_hash_lock, NULL);
1239 if (r != 0)
1240 goto free;
1241#endif
1242
1243 engine->storage_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
1244 if (engine->storage_hash == NULL)
1245 goto destroy_mutex;
1246
1247 return engine;
1248
1249 destroy_mutex:
1250#ifdef LIBETPAN_REENTRANT
1251 pthread_mutex_destroy(&engine->storage_hash_lock);
1252#endif
1253#if 0
1254 finder_done:
1255 message_folder_finder_done(&engine->msg_folder_finder);
1256#endif
1257 free:
1258 free(engine);
1259 err:
1260 return NULL;
1261}
1262
1263void libetpan_engine_free(struct mailengine * engine)
1264{
1265 chash_free(engine->storage_hash);
1266#ifdef LIBETPAN_REENTRANT
1267 pthread_mutex_destroy(&engine->storage_hash_lock);
1268#endif
1269#if 0
1270 message_folder_finder_done(&engine->msg_folder_finder);
1271#endif
1272 free(engine);
1273}
1274
1275#if 0
1276static struct folder_ref_info *
1277message_get_folder_ref(struct mailengine * engine,
1278 mailmessage * msg)
1279{
1280 struct mailfolder * folder;
1281 struct mailstorage * storage;
1282 struct storage_ref_info * storage_ref_info;
1283 struct folder_ref_info * folder_ref_info;
1284
1285 folder = message_folder_finder_lookup(&engine->msg_folder_finder, msg);
1286 if (folder == NULL)
1287 storage = NULL;
1288 else
1289 storage = folder->fld_storage;
1290
1291 storage_ref_info = get_storage_ref_info(engine, storage);
1292
1293 folder_ref_info = storage_get_folder_ref(storage_ref_info, folder);
1294
1295 return folder_ref_info;
1296}
1297#endif
1298
1299static struct folder_ref_info *
1300message_get_folder_ref(struct mailengine * engine,
1301 mailmessage * msg)
1302{
1303 struct mailfolder * folder;
1304 struct mailstorage * storage;
1305 struct storage_ref_info * storage_ref_info;
1306 struct folder_ref_info * folder_ref_info;
1307
1308 folder = msg->msg_folder;
1309 if (folder == NULL)
1310 storage = NULL;
1311 else
1312 storage = folder->fld_storage;
1313
1314 storage_ref_info = get_storage_ref_info(engine, storage);
1315
1316 folder_ref_info = storage_get_folder_ref(storage_ref_info, folder);
1317
1318 return folder_ref_info;
1319}
1320
1321int libetpan_message_ref(struct mailengine * engine,
1322 mailmessage * msg)
1323{
1324 struct folder_ref_info * ref_info;
1325
1326 ref_info = message_get_folder_ref(engine, msg);
1327
1328 return folder_message_ref(ref_info, msg);
1329}
1330
1331int libetpan_message_unref(struct mailengine * engine,
1332 mailmessage * msg)
1333{
1334 struct folder_ref_info * ref_info;
1335
1336 ref_info = message_get_folder_ref(engine, msg);
1337
1338 return folder_message_unref(ref_info, msg);
1339}
1340
1341
1342int libetpan_message_mime_ref(struct mailengine * engine,
1343 mailmessage * msg)
1344{
1345 struct folder_ref_info * ref_info;
1346
1347 ref_info = message_get_folder_ref(engine, msg);
1348
1349 return folder_message_mime_ref(engine->privacy, ref_info, msg);
1350}
1351
1352int libetpan_message_mime_unref(struct mailengine * engine,
1353 mailmessage * msg)
1354{
1355 struct folder_ref_info * ref_info;
1356
1357 ref_info = message_get_folder_ref(engine, msg);
1358
1359 return folder_message_mime_unref(engine->privacy, ref_info, msg);
1360}
1361
1362int libetpan_folder_get_msg_list(struct mailengine * engine,
1363 struct mailfolder * folder,
1364 struct mailmessage_list ** p_new_msg_list,
1365 struct mailmessage_list ** p_lost_msg_list)
1366{
1367 struct storage_ref_info * ref_info;
1368
1369 ref_info = get_storage_ref_info(engine, folder->fld_storage);
1370
1371 return storage_folder_get_msg_list(ref_info, folder,
1372 p_new_msg_list, p_lost_msg_list);
1373}
1374
1375int libetpan_folder_fetch_env_list(struct mailengine * engine,
1376 struct mailfolder * folder,
1377 struct mailmessage_list * msg_list)
1378{
1379 struct storage_ref_info * ref_info;
1380
1381 ref_info = get_storage_ref_info(engine, folder->fld_storage);
1382
1383 return storage_folder_fetch_env_list(ref_info, folder, msg_list);
1384}
1385
1386void libetpan_folder_free_msg_list(struct mailengine * engine,
1387 struct mailfolder * folder,
1388 struct mailmessage_list * env_list)
1389{
1390 struct storage_ref_info * ref_info;
1391
1392 ref_info = get_storage_ref_info(engine, folder->fld_storage);
1393
1394 storage_folder_free_msg_list(ref_info, folder, env_list);
1395}
1396
1397
1398int libetpan_storage_add(struct mailengine * engine,
1399 struct mailstorage * storage)
1400{
1401 struct storage_ref_info * storage_ref_info;
1402 struct folder_ref_info * folder_ref_info;
1403
1404 storage_ref_info = add_storage_ref_info(engine, storage);
1405 if (storage_ref_info == NULL)
1406 goto err;
1407
1408 if (storage == NULL) {
1409 folder_ref_info = storage_folder_add_ref(storage_ref_info, NULL);
1410 if (folder_ref_info == NULL)
1411 goto remove_storage_ref_info;
1412 }
1413
1414 return MAIL_NO_ERROR;
1415
1416 remove_storage_ref_info:
1417 remove_storage_ref_info(engine, storage);
1418 err:
1419 return MAIL_ERROR_MEMORY;
1420}
1421
1422void libetpan_storage_remove(struct mailengine * engine,
1423 struct mailstorage * storage)
1424{
1425 struct storage_ref_info * storage_ref_info;
1426
1427 storage_ref_info = get_storage_ref_info(engine, storage);
1428 if (storage == NULL) {
1429 storage_folder_remove_ref(storage_ref_info, NULL);
1430 }
1431
1432 remove_storage_ref_info(engine, storage);
1433}
1434
1435int libetpan_storage_connect(struct mailengine * engine,
1436 struct mailstorage * storage)
1437{
1438 struct storage_ref_info * ref_info;
1439
1440 ref_info = get_storage_ref_info(engine, storage);
1441
1442 return storage_connect(ref_info);
1443}
1444
1445
1446void libetpan_storage_disconnect(struct mailengine * engine,
1447 struct mailstorage * storage)
1448{
1449 struct storage_ref_info * ref_info;
1450
1451 ref_info = get_storage_ref_info(engine, storage);
1452
1453 storage_disconnect(ref_info);
1454}
1455
1456int libetpan_storage_used(struct mailengine * engine,
1457 struct mailstorage * storage)
1458{
1459 struct storage_ref_info * ref_info;
1460
1461 ref_info = get_storage_ref_info(engine, storage);
1462
1463 return (chash_count(ref_info->folder_ref_info) != 0);
1464}
1465
1466
1467int libetpan_folder_connect(struct mailengine * engine,
1468 struct mailfolder * folder)
1469{
1470 struct storage_ref_info * ref_info;
1471
1472 ref_info = get_storage_ref_info(engine, folder->fld_storage);
1473
1474 return storage_folder_connect(ref_info, folder);
1475}
1476
1477
1478void libetpan_folder_disconnect(struct mailengine * engine,
1479 struct mailfolder * folder)
1480{
1481 struct storage_ref_info * ref_info;
1482
1483 ref_info = get_storage_ref_info(engine, folder->fld_storage);
1484
1485 storage_folder_disconnect(ref_info, folder);
1486}
1487
1488
1489struct mailfolder *
1490libetpan_message_get_folder(struct mailengine * engine,
1491 mailmessage * msg)
1492{
1493#if 0
1494 return message_folder_finder_lookup(&engine->msg_folder_finder, msg);
1495#endif
1496 return msg->msg_folder;
1497}
1498
1499
1500struct mailstorage *
1501libetpan_message_get_storage(struct mailengine * engine,
1502 mailmessage * msg)
1503{
1504 struct mailfolder * folder;
1505
1506 folder = libetpan_message_get_folder(engine, msg);
1507
1508 if (folder == NULL)
1509 return NULL;
1510 else
1511 return folder->fld_storage;
1512}
1513
1514
1515int libetpan_message_register(struct mailengine * engine,
1516 struct mailfolder * folder,
1517 mailmessage * msg)
1518{
1519 struct storage_ref_info * storage_ref_info;
1520 int r;
1521 int res;
1522 struct folder_ref_info * folder_ref_info;
1523 struct mailstorage * storage;
1524
1525#if 0
1526 r = message_folder_finder_store(&engine->msg_folder_finder, msg, folder);
1527 if (r != MAIL_NO_ERROR) {
1528 res = r;
1529 goto err;
1530 }
1531#endif
1532
1533 if (folder != NULL)
1534 storage = folder->fld_storage;
1535 else
1536 storage = NULL;
1537
1538 storage_ref_info = get_storage_ref_info(engine, storage);
1539
1540 folder_ref_info = storage_get_folder_ref(storage_ref_info, folder);
1541
1542 r = folder_message_add(folder_ref_info, msg);
1543 if (r != MAIL_NO_ERROR) {
1544 res = r;
1545 goto delete;
1546 }
1547
1548 return MAIL_NO_ERROR;
1549
1550 delete:
1551#if 0
1552 message_folder_finder_delete(&engine->msg_folder_finder, msg);
1553#endif
1554 err:
1555 return res;
1556}
1557
1558struct mailprivacy *
1559libetpan_engine_get_privacy(struct mailengine * engine)
1560{
1561 return engine->privacy;
1562}
1563
1564
1565static void folder_debug(struct folder_ref_info * folder_ref_info, FILE * f)
1566{
1567 fprintf(f, "folder debug -- begin\n");
1568 if (folder_ref_info->folder == NULL) {
1569 fprintf(f, "NULL folder\n");
1570 }
1571 else {
1572 if (folder_ref_info->folder->fld_virtual_name != NULL)
1573 fprintf(f, "folder %s\n", folder_ref_info->folder->fld_virtual_name);
1574 else
1575 fprintf(f, "folder [no name]\n");
1576 }
1577
1578 fprintf(f, "message count: %i\n", chash_count(folder_ref_info->msg_hash));
1579 fprintf(f, "UID count: %i\n", chash_count(folder_ref_info->uid_hash));
1580 fprintf(f, "folder debug -- end\n");
1581}
1582
1583static void storage_debug(struct storage_ref_info * storage_ref_info, FILE * f)
1584{
1585 chashiter * iter;
1586
1587 fprintf(f, "storage debug -- begin\n");
1588 if (storage_ref_info->storage == NULL) {
1589 fprintf(f, "NULL storage\n");
1590 }
1591 else {
1592 if (storage_ref_info->storage->sto_id != NULL)
1593 fprintf(f, "storage %s\n", storage_ref_info->storage->sto_id);
1594 else
1595 fprintf(f, "storage [no name]\n");
1596 }
1597 fprintf(f, "folder count: %i\n",
1598 chash_count(storage_ref_info->folder_ref_info));
1599
1600 for(iter = chash_begin(storage_ref_info->folder_ref_info) ; iter != NULL ;
1601 iter = chash_next(storage_ref_info->folder_ref_info, iter)) {
1602 chashdatum data;
1603 struct folder_ref_info * folder_ref_info;
1604
1605 chash_value(iter, &data);
1606 folder_ref_info = data.data;
1607
1608 folder_debug(folder_ref_info, f);
1609 }
1610 fprintf(f, "storage debug -- end\n");
1611}
1612
1613void libetpan_engine_debug(struct mailengine * engine, FILE * f)
1614{
1615 chashiter * iter;
1616
1617 fprintf(f, "mail engine debug -- begin\n");
1618
1619 for(iter = chash_begin(engine->storage_hash) ; iter != NULL ;
1620 iter = chash_next(engine->storage_hash, iter)) {
1621 chashdatum data;
1622 struct storage_ref_info * storage_ref_info;
1623
1624 chash_value(iter, &data);
1625 storage_ref_info = data.data;
1626
1627 storage_debug(storage_ref_info, f);
1628 }
1629
1630#if 0
1631 fprintf(f, "global message references: %i\n",
1632 chash_count(engine->msg_folder_finder.message_hash));
1633#endif
1634 fprintf(f, "mail engine debug -- end\n");
1635}
1636
diff --git a/libetpan/src/engine/mailengine.h b/libetpan/src/engine/mailengine.h
new file mode 100644
index 0000000..acb6a16
--- a/dev/null
+++ b/libetpan/src/engine/mailengine.h
@@ -0,0 +1,190 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILENGINE_H
37
38#define MAILENGINE_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailfolder.h>
42#include <libetpan/mailprivacy_types.h>
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48/*
49 to run things in thread, you must protect the storage again concurrency.
50*/
51
52
53/*
54 storage data
55*/
56
57struct mailengine *
58libetpan_engine_new(struct mailprivacy * privacy);
59
60void libetpan_engine_free(struct mailengine * engine);
61
62
63struct mailprivacy *
64libetpan_engine_get_privacy(struct mailengine * engine);
65
66
67/*
68 message ref and unref
69*/
70
71/*
72 these function can only take messages returned by get_msg_list()
73 as arguments.
74
75 these functions cannot fail.
76*/
77
78int libetpan_message_ref(struct mailengine * engine,
79 mailmessage * msg);
80
81int libetpan_message_unref(struct mailengine * engine,
82 mailmessage * msg);
83
84
85/*
86 when you want to access the MIME structure of the message
87 with msg->mime, you have to call libetpan_message_mime_ref()
88 and libetpan_message_mime_unref() when you have finished.
89
90 if libetpan_mime_ref() returns a value <= 0, it means this failed.
91 the value is -MAIL_ERROR_XXX
92*/
93
94int libetpan_message_mime_ref(struct mailengine * engine,
95 mailmessage * msg);
96
97int libetpan_message_mime_unref(struct mailengine * engine,
98 mailmessage * msg);
99
100/*
101 message list
102*/
103
104/*
105 libetpan_folder_get_msg_list()
106
107 This function returns two list.
108 - List of lost message (the messages that were previously returned
109 but that does no more exist) (p_lost_msg_list)
110 - List of valid messages (p_new_msg_list).
111
112 These two list can only be freed by libetpan_folder_free_msg_list()
113*/
114
115int libetpan_folder_get_msg_list(struct mailengine * engine,
116 struct mailfolder * folder,
117 struct mailmessage_list ** p_new_msg_list,
118 struct mailmessage_list ** p_lost_msg_list);
119
120int libetpan_folder_fetch_env_list(struct mailengine * engine,
121 struct mailfolder * folder,
122 struct mailmessage_list * msg_list);
123
124void libetpan_folder_free_msg_list(struct mailengine * engine,
125 struct mailfolder * folder,
126 struct mailmessage_list * env_list);
127
128
129/*
130 connect and disconnect storage
131*/
132
133int libetpan_storage_add(struct mailengine * engine,
134 struct mailstorage * storage);
135
136void libetpan_storage_remove(struct mailengine * engine,
137 struct mailstorage * storage);
138
139int libetpan_storage_connect(struct mailengine * engine,
140 struct mailstorage * storage);
141
142void libetpan_storage_disconnect(struct mailengine * engine,
143 struct mailstorage * storage);
144
145int libetpan_storage_used(struct mailengine * engine,
146 struct mailstorage * storage);
147
148
149/*
150 libetpan_folder_connect()
151 libetpan_folder_disconnect()
152
153 You can disconnect the folder only when you have freed all the message
154 you were given.
155*/
156
157int libetpan_folder_connect(struct mailengine * engine,
158 struct mailfolder * folder);
159
160void libetpan_folder_disconnect(struct mailengine * engine,
161 struct mailfolder * folder);
162
163
164struct mailfolder *
165libetpan_message_get_folder(struct mailengine * engine,
166 mailmessage * msg);
167
168struct mailstorage *
169libetpan_message_get_storage(struct mailengine * engine,
170 mailmessage * msg);
171
172
173/*
174 register a message
175*/
176
177int libetpan_message_register(struct mailengine * engine,
178 struct mailfolder * folder,
179 mailmessage * msg);
180
181
182void libetpan_engine_debug(struct mailengine * engine, FILE * f);
183
184extern void * engine_app;
185
186#ifdef __cplusplus
187}
188#endif
189
190#endif
diff --git a/libetpan/src/engine/mailprivacy.c b/libetpan/src/engine/mailprivacy.c
new file mode 100644
index 0000000..99cc50f
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy.c
@@ -0,0 +1,949 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailprivacy.h"
37
38#include <libetpan/libetpan.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46#include "mailprivacy_tools.h"
47
48carray * mailprivacy_get_protocols(struct mailprivacy * privacy)
49{
50 return privacy->protocols;
51}
52
53static int recursive_check_privacy(struct mailprivacy * privacy,
54 mailmessage * msg,
55 struct mailmime * mime);
56
57static int check_tmp_dir(char * tmp_dir)
58{
59 struct stat stat_info;
60 int r;
61
62 r = stat(tmp_dir, &stat_info);
63 if (r < 0)
64 return MAIL_ERROR_FILE;
65
66 /* check if the directory belongs to the user */
67 if (stat_info.st_uid != getuid())
68 return MAIL_ERROR_INVAL;
69
70 if ((stat_info.st_mode & 00777) != 0700) {
71 r = chmod(tmp_dir, 0700);
72 if (r < 0)
73 return MAIL_ERROR_FILE;
74 }
75
76 return MAIL_NO_ERROR;
77}
78
79struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative)
80{
81 struct mailprivacy * privacy;
82 int r;
83
84#if 0
85 r = check_tmp_dir(tmp_dir);
86 if (r != MAIL_NO_ERROR)
87 goto err;
88#endif
89
90 privacy = malloc(sizeof(* privacy));
91 if (privacy == NULL)
92 goto err;
93
94 privacy->tmp_dir = strdup(tmp_dir);
95 if (privacy->tmp_dir == NULL)
96 goto free;
97
98 privacy->msg_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
99 if (privacy->msg_ref == NULL)
100 goto free_tmp_dir;
101
102 privacy->mmapstr = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
103 if (privacy->mmapstr == NULL)
104 goto free_msg_ref;
105
106 privacy->mime_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
107 if (privacy->mime_ref == NULL)
108 goto free_mmapstr;
109
110 privacy->protocols = carray_new(16);
111 if (privacy->protocols == NULL)
112 goto free_mime_ref;
113
114 privacy->make_alternative = make_alternative;
115
116 return privacy;
117
118 free_mime_ref:
119 chash_free(privacy->mime_ref);
120 free_mmapstr:
121 chash_free(privacy->mmapstr);
122 free_msg_ref:
123 chash_free(privacy->msg_ref);
124 free_tmp_dir:
125 free(privacy->tmp_dir);
126 free:
127 free(privacy);
128 err:
129 return NULL;
130}
131
132void mailprivacy_free(struct mailprivacy * privacy)
133{
134 carray_free(privacy->protocols);
135 chash_free(privacy->mime_ref);
136 chash_free(privacy->mmapstr);
137 chash_free(privacy->msg_ref);
138 free(privacy->tmp_dir);
139 free(privacy);
140}
141
142static int msg_is_modified(struct mailprivacy * privacy,
143 mailmessage * msg)
144{
145 chashdatum key;
146 chashdatum data;
147 int r;
148
149 if (privacy == NULL)
150 return 0;
151
152 key.data = &msg;
153 key.len = sizeof(msg);
154
155 r = chash_get(privacy->msg_ref, &key, &data);
156 if (r < 0)
157 return 0;
158 else
159 return 1;
160}
161
162static int register_msg(struct mailprivacy * privacy,
163 mailmessage * msg)
164{
165 chashdatum key;
166 chashdatum data;
167 int r;
168
169 if (privacy == NULL)
170 return MAIL_NO_ERROR;
171
172 key.data = &msg;
173 key.len = sizeof(msg);
174 data.data = msg;
175 data.len = 0;
176
177 r = chash_set(privacy->msg_ref, &key, &data, NULL);
178 if (r < 0)
179 return MAIL_ERROR_MEMORY;
180 else
181 return MAIL_NO_ERROR;
182}
183
184static void unregister_message(struct mailprivacy * privacy,
185 mailmessage * msg)
186{
187 chashdatum key;
188
189 key.data = &msg;
190 key.len = sizeof(msg);
191
192 chash_delete(privacy->msg_ref, &key, NULL);
193}
194
195static int result_is_mmapstr(struct mailprivacy * privacy, char * str)
196{
197 chashdatum key;
198 chashdatum data;
199 int r;
200
201 key.data = &str;
202 key.len = sizeof(str);
203
204 r = chash_get(privacy->mmapstr, &key, &data);
205 if (r < 0)
206 return 0;
207 else
208 return 1;
209}
210
211static int register_result_mmapstr(struct mailprivacy * privacy,
212 char * content)
213{
214 chashdatum key;
215 chashdatum data;
216 int r;
217
218 key.data = &content;
219 key.len = sizeof(content);
220 data.data = content;
221 data.len = 0;
222
223 r = chash_set(privacy->mmapstr, &key, &data, NULL);
224 if (r < 0)
225 return MAIL_ERROR_MEMORY;
226
227 return 0;
228}
229
230static void unregister_result_mmapstr(struct mailprivacy * privacy,
231 char * str)
232{
233 chashdatum key;
234
235 mmap_string_unref(str);
236
237 key.data = &str;
238 key.len = sizeof(str);
239
240 chash_delete(privacy->mmapstr, &key, NULL);
241}
242
243static int register_mime(struct mailprivacy * privacy,
244 struct mailmime * mime)
245{
246 chashdatum key;
247 chashdatum data;
248 int r;
249
250 key.data = &mime;
251 key.len = sizeof(mime);
252 data.data = mime;
253 data.len = 0;
254
255 r = chash_set(privacy->mime_ref, &key, &data, NULL);
256 if (r < 0)
257 return MAIL_ERROR_MEMORY;
258 else
259 return MAIL_NO_ERROR;
260}
261
262static void unregister_mime(struct mailprivacy * privacy,
263 struct mailmime * mime)
264{
265 chashdatum key;
266
267 key.data = &mime;
268 key.len = sizeof(mime);
269
270 chash_delete(privacy->mime_ref, &key, NULL);
271}
272
273static int mime_is_registered(struct mailprivacy * privacy,
274 struct mailmime * mime)
275{
276 chashdatum key;
277 chashdatum data;
278 int r;
279
280 key.data = &mime;
281 key.len = sizeof(mime);
282
283 r = chash_get(privacy->mime_ref, &key, &data);
284 if (r < 0)
285 return 0;
286 else
287 return 1;
288}
289
290static int recursive_register_mime(struct mailprivacy * privacy,
291 struct mailmime * mime)
292{
293 clistiter * cur;
294 int r;
295
296 r = register_mime(privacy, mime);
297 if (r != MAIL_NO_ERROR)
298 return r;
299
300 switch (mime->mm_type) {
301 case MAILMIME_SINGLE:
302 break;
303
304 case MAILMIME_MULTIPLE:
305 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
306 cur != NULL ; cur = clist_next(cur)) {
307 struct mailmime * child;
308
309 child = clist_content(cur);
310
311 r = recursive_register_mime(privacy, child);
312 if (r != MAIL_NO_ERROR)
313 return r;
314 }
315 break;
316
317 case MAILMIME_MESSAGE:
318 if (mime->mm_data.mm_message.mm_msg_mime) {
319 r = recursive_register_mime(privacy,
320 mime->mm_data.mm_message.mm_msg_mime);
321 if (r != MAIL_NO_ERROR)
322 return r;
323 }
324 break;
325 }
326
327 return MAIL_NO_ERROR;
328}
329
330void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy,
331 struct mailmime * mime)
332{
333 clistiter * cur;
334
335 unregister_mime(privacy, mime);
336
337 switch (mime->mm_type) {
338 case MAILMIME_SINGLE:
339 break;
340
341 case MAILMIME_MULTIPLE:
342 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
343 cur != NULL ; cur = clist_next(cur)) {
344 struct mailmime * child;
345
346 child = clist_content(cur);
347
348 mailprivacy_recursive_unregister_mime(privacy, child);
349 }
350 break;
351
352 case MAILMIME_MESSAGE:
353 if (mime->mm_data.mm_message.mm_msg_mime)
354 mailprivacy_recursive_unregister_mime(privacy,
355 mime->mm_data.mm_message.mm_msg_mime);
356 break;
357 }
358}
359
360static void recursive_clear_registered_mime(struct mailprivacy * privacy,
361 struct mailmime * mime)
362{
363 clistiter * cur;
364 struct mailmime_data * data;
365
366 switch (mime->mm_type) {
367 case MAILMIME_SINGLE:
368 if (mime_is_registered(privacy, mime)) {
369 data = mime->mm_data.mm_single;
370 if (data != NULL) {
371 if (data->dt_type == MAILMIME_DATA_FILE)
372 unlink(data->dt_data.dt_filename);
373 }
374 }
375 break;
376
377 case MAILMIME_MULTIPLE:
378 if (mime_is_registered(privacy, mime)) {
379 data = mime->mm_data.mm_multipart.mm_preamble;
380 if (data != NULL) {
381 if (data->dt_type == MAILMIME_DATA_FILE)
382 unlink(data->dt_data.dt_filename);
383 }
384 data = mime->mm_data.mm_multipart.mm_epilogue;
385 if (data != NULL) {
386 if (data->dt_type == MAILMIME_DATA_FILE)
387 unlink(data->dt_data.dt_filename);
388 }
389 }
390 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
391 cur != NULL ; cur = clist_next(cur)) {
392 struct mailmime * child;
393
394 child = clist_content(cur);
395
396 recursive_clear_registered_mime(privacy, child);
397 }
398 break;
399
400 case MAILMIME_MESSAGE:
401 if (mime->mm_data.mm_message.mm_msg_mime)
402 recursive_clear_registered_mime(privacy,
403 mime->mm_data.mm_message.mm_msg_mime);
404 break;
405 }
406 unregister_mime(privacy, mime);
407}
408
409
410/* **************************************************** */
411/* fetch operations start here */
412
413
414static void recursive_clear_registered_mime(struct mailprivacy * privacy,
415 struct mailmime * mime);
416
417#if 0
418static void display_recursive_part(struct mailmime * mime)
419{
420 clistiter * cur;
421
422 fprintf(stderr, "part %p\n", mime->mm_body);
423 switch (mime->mm_type) {
424 case MAILMIME_SINGLE:
425 fprintf(stderr, "single %p - %i\n", mime->mm_data.mm_single,
426 mime->mm_data.mm_single->dt_type);
427 if (mime->mm_data.mm_single->dt_type == MAILMIME_DATA_TEXT) {
428 fprintf(stderr, "data : %p %i\n",
429 mime->mm_data.mm_single->dt_data.dt_text.dt_data,
430 mime->mm_data.mm_single->dt_data.dt_text.dt_length);
431 }
432 break;
433 case MAILMIME_MESSAGE:
434 fprintf(stderr, "message %p\n", mime->mm_data.mm_message.mm_msg_mime);
435 display_recursive_part(mime->mm_data.mm_message.mm_msg_mime);
436 break;
437 case MAILMIME_MULTIPLE:
438 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ;
439 cur = clist_next(cur)) {
440
441 fprintf(stderr, "multipart\n");
442 display_recursive_part(clist_content(cur));
443 }
444 break;
445 }
446}
447#endif
448
449int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy,
450 mailmessage * msg_info,
451 struct mailmime ** result)
452{
453 int r;
454 struct mailmime * mime;
455
456 if (msg_info->msg_mime != NULL)
457 return MAIL_NO_ERROR;
458
459 if (msg_is_modified(privacy, msg_info))
460 return MAIL_NO_ERROR;
461
462 r = mailmessage_get_bodystructure(msg_info, &mime);
463 if (r != MAIL_NO_ERROR)
464 return r;
465
466 /* modification on message if necessary */
467 r = recursive_check_privacy(privacy, msg_info, msg_info->msg_mime);
468 if (r != MAIL_NO_ERROR) {
469 * result = msg_info->msg_mime;
470 return MAIL_NO_ERROR;
471 }
472
473 r = register_msg(privacy, msg_info);
474 if (r != MAIL_NO_ERROR) {
475 recursive_clear_registered_mime(privacy, mime);
476 mailmessage_flush(msg_info);
477 return MAIL_ERROR_MEMORY;
478 }
479
480 * result = msg_info->msg_mime;
481
482 return MAIL_NO_ERROR;
483}
484
485void mailprivacy_msg_flush(struct mailprivacy * privacy,
486 mailmessage * msg_info)
487{
488 if (msg_is_modified(privacy, msg_info)) {
489 /* remove all modified parts */
490 if (msg_info->msg_mime != NULL)
491 recursive_clear_registered_mime(privacy, msg_info->msg_mime);
492 unregister_message(privacy, msg_info);
493 }
494
495 mailmessage_flush(msg_info);
496}
497
498static int fetch_registered_part(struct mailprivacy * privacy,
499 int (* fetch_section)(mailmessage *, struct mailmime *,
500 char **, size_t *),
501 struct mailmime * mime,
502 char ** result, size_t * result_len)
503{
504 mailmessage * dummy_msg;
505 int res;
506 char * content;
507 size_t content_len;
508 int r;
509
510 dummy_msg = mime_message_init(NULL);
511 if (dummy_msg == NULL) {
512 res = MAIL_ERROR_MEMORY;
513 goto err;
514 }
515
516 r = mime_message_set_tmpdir(dummy_msg, privacy->tmp_dir);
517 if (r != MAIL_NO_ERROR) {
518 res = MAIL_ERROR_MEMORY;
519 goto free_msg;
520 }
521
522 r = fetch_section(dummy_msg, mime, &content, &content_len);
523 if (r != MAIL_NO_ERROR) {
524 res = r;
525 goto free_msg;
526 }
527
528 r = register_result_mmapstr(privacy, content);
529 if (r != MAIL_NO_ERROR) {
530 res = r;
531 goto free_fetch;
532 }
533
534 mailmessage_free(dummy_msg);
535
536 * result = content;
537 * result_len = content_len;
538
539 return MAIL_NO_ERROR;
540
541 free_fetch:
542 mailmessage_fetch_result_free(dummy_msg, content);
543 free_msg:
544 mailmessage_free(dummy_msg);
545 err:
546 return res;
547}
548
549int mailprivacy_msg_fetch_section(struct mailprivacy * privacy,
550 mailmessage * msg_info,
551 struct mailmime * mime,
552 char ** result, size_t * result_len)
553{
554 if (msg_is_modified(privacy, msg_info) &&
555 mime_is_registered(privacy, mime)) {
556 return fetch_registered_part(privacy, mailmessage_fetch_section,
557 mime, result, result_len);
558 }
559
560 return mailmessage_fetch_section(msg_info, mime, result, result_len);
561}
562
563int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy,
564 mailmessage * msg_info,
565 struct mailmime * mime,
566 char ** result,
567 size_t * result_len)
568{
569 if (msg_is_modified(privacy, msg_info) &&
570 mime_is_registered(privacy, mime)) {
571 return fetch_registered_part(privacy, mailmessage_fetch_section_header,
572 mime, result, result_len);
573 }
574
575 return mailmessage_fetch_section_header(msg_info, mime, result, result_len);
576}
577
578int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy,
579 mailmessage * msg_info,
580 struct mailmime * mime,
581 char ** result,
582 size_t * result_len)
583{
584 if (msg_is_modified(privacy, msg_info) &&
585 mime_is_registered(privacy, mime)) {
586 return fetch_registered_part(privacy, mailmessage_fetch_section_mime,
587 mime, result, result_len);
588 }
589
590 return mailmessage_fetch_section_mime(msg_info, mime, result, result_len);
591}
592
593int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy,
594 mailmessage * msg_info,
595 struct mailmime * mime,
596 char ** result,
597 size_t * result_len)
598{
599 if (msg_is_modified(privacy, msg_info) &&
600 mime_is_registered(privacy, mime)) {
601 return fetch_registered_part(privacy, mailmessage_fetch_section_body,
602 mime, result, result_len);
603 }
604
605 return mailmessage_fetch_section_body(msg_info, mime, result, result_len);
606}
607
608void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy,
609 mailmessage * msg_info,
610 char * msg)
611{
612 if (msg == NULL)
613 return;
614
615 if (msg_is_modified(privacy, msg_info)) {
616 if (result_is_mmapstr(privacy, msg)) {
617 unregister_result_mmapstr(privacy, msg);
618 return;
619 }
620 }
621
622 mailmessage_fetch_result_free(msg_info, msg);
623}
624
625int mailprivacy_msg_fetch(struct mailprivacy * privacy,
626 mailmessage * msg_info,
627 char ** result,
628 size_t * result_len)
629{
630 return mailmessage_fetch(msg_info, result, result_len);
631}
632
633int mailprivacy_msg_fetch_header(struct mailprivacy * privacy,
634 mailmessage * msg_info,
635 char ** result,
636 size_t * result_len)
637{
638 return mailmessage_fetch_header(msg_info, result, result_len);
639}
640
641/* end of fetch operations */
642/* **************************************************** */
643
644static int privacy_handler(struct mailprivacy * privacy,
645 mailmessage * msg,
646 struct mailmime * mime, struct mailmime ** result);
647
648
649
650static struct mailmime *
651mime_add_alternative(struct mailprivacy * privacy,
652 mailmessage * msg,
653 struct mailmime * mime,
654 struct mailmime * alternative)
655{
656 struct mailmime * multipart;
657 int r;
658 struct mailmime * mime_copy;
659 char original_filename[PATH_MAX];
660
661 if (mime->mm_parent == NULL)
662 goto err;
663
664 r = mailmime_new_with_content("multipart/alternative", NULL, &multipart);
665 if (r != MAILIMF_NO_ERROR)
666 goto err;
667
668 r = mailmime_smart_add_part(multipart, alternative);
669 if (r != MAILIMF_NO_ERROR) {
670 goto free_multipart;
671 }
672
673 /* get copy of mime part "mime" and set parts */
674
675 r = mailprivacy_fetch_mime_body_to_file(privacy,
676 original_filename, sizeof(original_filename),
677 msg, mime);
678 if (r != MAIL_NO_ERROR)
679 goto detach_alternative;
680
681 r = mailprivacy_get_part_from_file(privacy, 0,
682 original_filename, &mime_copy);
683 unlink(original_filename);
684 if (r != MAIL_NO_ERROR) {
685 goto detach_alternative;
686 }
687
688 r = mailmime_smart_add_part(multipart, mime_copy);
689 if (r != MAILIMF_NO_ERROR) {
690 goto free_mime_copy;
691 }
692
693 r = recursive_register_mime(privacy, multipart);
694 if (r != MAIL_NO_ERROR)
695 goto detach_mime_copy;
696
697 mailmime_substitute(mime, multipart);
698
699 mailmime_free(mime);
700
701 return multipart;
702
703 detach_mime_copy:
704 mailprivacy_recursive_unregister_mime(privacy, multipart);
705 mailmime_remove_part(alternative);
706 free_mime_copy:
707 mailprivacy_mime_clear(mime_copy);
708 mailmime_free(mime_copy);
709 detach_alternative:
710 mailmime_remove_part(alternative);
711 free_multipart:
712 mailmime_free(multipart);
713 err:
714 return NULL;
715}
716
717/*
718 recursive_check_privacy returns MAIL_NO_ERROR if at least one
719 part is using a privacy protocol.
720*/
721
722static int recursive_check_privacy(struct mailprivacy * privacy,
723 mailmessage * msg,
724 struct mailmime * mime)
725{
726 int r;
727 clistiter * cur;
728 struct mailmime * alternative;
729 int res;
730 struct mailmime * multipart;
731
732 if (privacy == NULL)
733 return MAIL_NO_ERROR;
734
735 if (mime_is_registered(privacy, mime))
736 return MAIL_ERROR_INVAL;
737
738 r = privacy_handler(privacy, msg, mime, &alternative);
739 if (r == MAIL_NO_ERROR) {
740 if (privacy->make_alternative) {
741 multipart = mime_add_alternative(privacy, msg, mime, alternative);
742 if (multipart == NULL) {
743 mailprivacy_mime_clear(alternative);
744 mailmime_free(alternative);
745 return MAIL_ERROR_MEMORY;
746 }
747 }
748 else {
749 mailmime_substitute(mime, alternative);
750 mailmime_free(mime);
751 mime = NULL;
752 }
753
754 return MAIL_NO_ERROR;
755 }
756 else {
757 switch (mime->mm_type) {
758 case MAILMIME_SINGLE:
759 return MAIL_ERROR_INVAL;
760
761 case MAILMIME_MULTIPLE:
762 res = MAIL_ERROR_INVAL;
763
764 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
765 cur != NULL ; cur = clist_next(cur)) {
766 struct mailmime * child;
767
768 child = clist_content(cur);
769
770 r = recursive_check_privacy(privacy, msg, child);
771 if (r == MAIL_NO_ERROR)
772 res = MAIL_NO_ERROR;
773 }
774
775 return res;
776
777 case MAILMIME_MESSAGE:
778 if (mime->mm_data.mm_message.mm_msg_mime != NULL)
779 return recursive_check_privacy(privacy, msg,
780 mime->mm_data.mm_message.mm_msg_mime);
781 return MAIL_ERROR_INVAL;
782
783 default:
784 return MAIL_ERROR_INVAL;
785 }
786 }
787}
788
789static int privacy_handler(struct mailprivacy * privacy,
790 mailmessage * msg,
791 struct mailmime * mime, struct mailmime ** result)
792{
793 int r;
794 struct mailmime * alternative_mime;
795 unsigned int i;
796
797 alternative_mime = NULL;
798 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
799 struct mailprivacy_protocol * protocol;
800
801 protocol = carray_get(privacy->protocols, i);
802
803 if (protocol->decrypt != NULL) {
804 r = protocol->decrypt(privacy, msg, mime, &alternative_mime);
805 if (r == MAIL_NO_ERROR) {
806
807 * result = alternative_mime;
808
809 return MAIL_NO_ERROR;
810 }
811 }
812 }
813
814 return MAIL_ERROR_INVAL;
815}
816
817int mailprivacy_register(struct mailprivacy * privacy,
818 struct mailprivacy_protocol * protocol)
819{
820 int r;
821
822 r = carray_add(privacy->protocols, protocol, NULL);
823 if (r < 0)
824 return MAIL_ERROR_MEMORY;
825
826 return MAIL_NO_ERROR;
827}
828
829void mailprivacy_unregister(struct mailprivacy * privacy,
830 struct mailprivacy_protocol * protocol)
831{
832 unsigned int i;
833
834 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
835 if (carray_get(privacy->protocols, i) == protocol) {
836 carray_delete(privacy->protocols, i);
837 return;
838 }
839 }
840}
841
842static struct mailprivacy_protocol *
843get_protocol(struct mailprivacy * privacy, char * privacy_driver)
844{
845 unsigned int i;
846
847 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
848 struct mailprivacy_protocol * protocol;
849
850 protocol = carray_get(privacy->protocols, i);
851 if (strcasecmp(protocol->name, privacy_driver) == 0)
852 return protocol;
853 }
854
855 return NULL;
856}
857
858static struct mailprivacy_encryption *
859get_encryption(struct mailprivacy_protocol * protocol,
860 char * privacy_encryption)
861{
862 int i;
863
864 for(i = 0 ; i < protocol->encryption_count ; i ++) {
865 struct mailprivacy_encryption * encryption;
866
867 encryption = &protocol->encryption_tab[i];
868 if (strcasecmp(encryption->name, privacy_encryption) == 0)
869 return encryption;
870 }
871
872 return NULL;
873}
874
875int mailprivacy_encrypt(struct mailprivacy * privacy,
876 char * privacy_driver, char * privacy_encryption,
877 struct mailmime * mime,
878 struct mailmime ** result)
879{
880 struct mailprivacy_protocol * protocol;
881 struct mailprivacy_encryption * encryption;
882 int r;
883
884 protocol = get_protocol(privacy, privacy_driver);
885 if (protocol == NULL)
886 return MAIL_ERROR_INVAL;
887
888 encryption = get_encryption(protocol, privacy_encryption);
889 if (encryption == NULL)
890 return MAIL_ERROR_INVAL;
891
892 if (encryption->encrypt == NULL)
893 return MAIL_ERROR_NOT_IMPLEMENTED;
894
895 r = encryption->encrypt(privacy, mime, result);
896 if (r != MAIL_NO_ERROR)
897 return r;
898
899 return MAIL_NO_ERROR;
900}
901
902char * mailprivacy_get_encryption_name(struct mailprivacy * privacy,
903 char * privacy_driver, char * privacy_encryption)
904{
905 struct mailprivacy_protocol * protocol;
906 struct mailprivacy_encryption * encryption;
907
908 protocol = get_protocol(privacy, privacy_driver);
909 if (protocol == NULL)
910 return NULL;
911
912 encryption = get_encryption(protocol, privacy_encryption);
913 if (encryption == NULL)
914 return NULL;
915
916 return encryption->description;
917}
918
919int mailprivacy_is_encrypted(struct mailprivacy * privacy,
920 mailmessage * msg,
921 struct mailmime * mime)
922{
923 unsigned int i;
924
925 if (mime_is_registered(privacy, mime))
926 return 0;
927
928 for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) {
929 struct mailprivacy_protocol * protocol;
930
931 protocol = carray_get(privacy->protocols, i);
932
933 if (protocol->is_encrypted != NULL) {
934 if (protocol->is_encrypted(privacy, msg, mime))
935 return 1;
936 }
937 }
938
939 return 0;
940}
941
942void mailprivacy_debug(struct mailprivacy * privacy, FILE * f)
943{
944 fprintf(f, "privacy debug -- begin\n");
945 fprintf(f, "registered message: %i\n", chash_count(privacy->msg_ref));
946 fprintf(f, "registered MMAPStr: %i\n", chash_count(privacy->mmapstr));
947 fprintf(f, "registered mailmime: %i\n", chash_count(privacy->mime_ref));
948 fprintf(f, "privacy debug -- end\n");
949}
diff --git a/libetpan/src/engine/mailprivacy.h b/libetpan/src/engine/mailprivacy.h
new file mode 100644
index 0000000..1f77331
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy.h
@@ -0,0 +1,117 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPRIVACY_H
37
38#define MAILPRIVACY_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailprivacy_types.h>
42#include <libetpan/mailprivacy_tools.h>
43
44struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative);
45
46void mailprivacy_free(struct mailprivacy * privacy);
47
48int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy,
49 mailmessage * msg_info,
50 struct mailmime ** result);
51
52void mailprivacy_msg_flush(struct mailprivacy * privacy,
53 mailmessage * msg_info);
54
55int mailprivacy_msg_fetch_section(struct mailprivacy * privacy,
56 mailmessage * msg_info,
57 struct mailmime * mime,
58 char ** result, size_t * result_len);
59
60int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy,
61 mailmessage * msg_info,
62 struct mailmime * mime,
63 char ** result,
64 size_t * result_len);
65
66int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy,
67 mailmessage * msg_info,
68 struct mailmime * mime,
69 char ** result,
70 size_t * result_len);
71
72int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy,
73 mailmessage * msg_info,
74 struct mailmime * mime,
75 char ** result,
76 size_t * result_len);
77
78void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy,
79 mailmessage * msg_info,
80 char * msg);
81
82int mailprivacy_msg_fetch(struct mailprivacy * privacy,
83 mailmessage * msg_info,
84 char ** result,
85 size_t * result_len);
86
87int mailprivacy_msg_fetch_header(struct mailprivacy * privacy,
88 mailmessage * msg_info,
89 char ** result,
90 size_t * result_len);
91
92int mailprivacy_register(struct mailprivacy * privacy,
93 struct mailprivacy_protocol * protocol);
94
95void mailprivacy_unregister(struct mailprivacy * privacy,
96 struct mailprivacy_protocol * protocol);
97
98char * mailprivacy_get_encryption_name(struct mailprivacy * privacy,
99 char * privacy_driver, char * privacy_encryption);
100
101int mailprivacy_encrypt(struct mailprivacy * privacy,
102 char * privacy_driver, char * privacy_encryption,
103 struct mailmime * mime,
104 struct mailmime ** result);
105
106void mailprivacy_debug(struct mailprivacy * privacy, FILE * f);
107
108carray * mailprivacy_get_protocols(struct mailprivacy * privacy);
109
110int mailprivacy_is_encrypted(struct mailprivacy * privacy,
111 mailmessage * msg,
112 struct mailmime * mime);
113
114void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy,
115 struct mailmime * mime);
116
117#endif
diff --git a/libetpan/src/engine/mailprivacy_gnupg.c b/libetpan/src/engine/mailprivacy_gnupg.c
new file mode 100644
index 0000000..01dcc80
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_gnupg.c
@@ -0,0 +1,2614 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailprivacy_gnupg.h"
37
38#include "mailprivacy.h"
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <string.h>
45#include <sys/wait.h>
46#include <stdlib.h>
47#include "mailprivacy_tools.h"
48#include <libetpan/mailmime.h>
49#include <libetpan/libetpan-config.h>
50
51static int pgp_is_encrypted(struct mailmime * mime)
52{
53 if (mime->mm_content_type != NULL) {
54 clistiter * cur;
55
56 if (strcasecmp(mime->mm_content_type->ct_subtype, "encrypted") != 0)
57 return 0;
58
59 for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; cur != NULL ;
60 cur = clist_next(cur)) {
61 struct mailmime_parameter * param;
62
63 param = clist_content(cur);
64
65 if ((strcasecmp(param->pa_name, "protocol") == 0) &&
66 (strcasecmp(param->pa_value, "application/pgp-encrypted") == 0))
67 return 1;
68 }
69 }
70
71 return 0;
72}
73
74static int pgp_is_signed(struct mailmime * mime)
75{
76 if (mime->mm_content_type != NULL) {
77 clistiter * cur;
78
79 if (strcasecmp(mime->mm_content_type->ct_subtype, "signed") != 0)
80 return 0;
81
82 for(cur = clist_begin(mime->mm_content_type->ct_parameters) ;
83 cur != NULL ; cur = clist_next(cur)) {
84 struct mailmime_parameter * param;
85
86 param = clist_content(cur);
87
88 if ((strcasecmp(param->pa_name, "protocol") == 0) &&
89 (strcasecmp(param->pa_value, "application/pgp-signature") == 0))
90 return 1;
91 }
92 }
93
94 return 0;
95}
96
97#define PGP_SIGNED "-----BEGIN PGP SIGNED MESSAGE-----"
98
99int pgp_is_clearsigned(char * data, size_t len)
100{
101 if (len >= strlen(PGP_SIGNED))
102 if (strncmp(data, PGP_SIGNED, sizeof(PGP_SIGNED) - 1) == 0)
103 return 1;
104
105 return 0;
106}
107
108#define PGP_CRYPTED "-----BEGIN PGP MESSAGE-----"
109
110int pgp_is_crypted_armor(char * data, size_t len)
111{
112 if (len >= strlen(PGP_CRYPTED))
113 if (strncmp(data, PGP_CRYPTED, sizeof(PGP_CRYPTED) - 1) == 0)
114 return 1;
115
116 return 0;
117}
118
119
120#define BUF_SIZE 1024
121
122enum {
123 NO_ERROR_PGP = 0,
124 ERROR_PGP_CHECK,
125 ERROR_PGP_COMMAND,
126 ERROR_PGP_FILE,
127};
128
129/* write output to a file */
130
131static int get_pgp_output(FILE * dest_f, char * command)
132{
133 FILE * p;
134 char buf[BUF_SIZE];
135 size_t size;
136 int res;
137 int status;
138 char command_redirected[PATH_MAX];
139
140 snprintf(command_redirected, sizeof(command_redirected), "%s 2>&1", command);
141
142 /*
143 flush buffer so that it is not flushed more than once when forking
144 */
145 fflush(dest_f);
146
147 p = popen(command_redirected, "r");
148 if (p == NULL) {
149 res = ERROR_PGP_COMMAND;
150 goto err;
151 }
152
153 while ((size = fread(buf, 1, sizeof(buf), p)) != 0) {
154 size_t written;
155
156 written = fwrite(buf, 1, size, dest_f);
157 if (written != size) {
158 res = ERROR_PGP_FILE;
159 goto close;
160 }
161 }
162 status = pclose(p);
163
164 if (WEXITSTATUS(status) != 0)
165 return ERROR_PGP_CHECK;
166 else
167 return NO_ERROR_PGP;
168
169 close:
170 pclose(p);
171 err:
172 return res;
173}
174
175#define PGP_DECRYPT_DESCRIPTION "PGP encrypted part\r\n"
176#define PGP_DECRYPT_FAILED "PGP decryption FAILED\r\n"
177#define PGP_DECRYPT_SUCCESS "PGP decryption success\r\n"
178
179/* extracted from mailprivacy_smime.c -- begin */
180
181static char * get_first_from_addr(struct mailmime * mime)
182{
183 clistiter * cur;
184 struct mailimf_single_fields single_fields;
185 struct mailimf_fields * fields;
186 struct mailimf_mailbox * mb;
187
188 if (mime->mm_type != MAILMIME_MESSAGE)
189 return NULL;
190
191 fields = mime->mm_data.mm_message.mm_fields;
192 if (fields == NULL)
193 return NULL;
194
195 mailimf_single_fields_init(&single_fields, fields);
196
197 if (single_fields.fld_from == NULL)
198 return NULL;
199
200 cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list);
201 if (cur == NULL)
202 return NULL;
203
204 mb = clist_content(cur);
205
206 return mb->mb_addr_spec;
207}
208
209/* extracted from mailprivacy_smime.c -- end */
210
211static int pgp_decrypt(struct mailprivacy * privacy,
212 mailmessage * msg,
213 struct mailmime * mime, struct mailmime ** result)
214{
215 char default_key[PATH_MAX];
216 struct mailmime * version_mime;
217 struct mailmime * encrypted_mime;
218 clistiter * cur;
219 char encrypted_filename[PATH_MAX];
220 char description_filename[PATH_MAX];
221 FILE * description_f;
222 char decrypted_filename[PATH_MAX];
223 FILE * decrypted_f;
224 char command[PATH_MAX];
225 struct mailmime * description_mime;
226 struct mailmime * decrypted_mime;
227 int r;
228 int res;
229 int decrypt_ok;
230 char quoted_decrypted_filename[PATH_MAX];
231 char quoted_encrypted_filename[PATH_MAX];
232 struct mailmime * multipart;
233 char * email;
234
235 /* get the two parts of the PGP message */
236
237 cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list);
238 if (cur == NULL) {
239 res = MAIL_ERROR_INVAL;
240 goto err;
241 }
242
243 version_mime = clist_content(cur);
244 cur = clist_next(cur);
245 if (cur == NULL) {
246 res = MAIL_ERROR_INVAL;
247 goto err;
248 }
249
250 encrypted_mime = clist_content(cur);
251
252 /* fetch the second section, that's the useful one */
253
254 r = mailprivacy_fetch_decoded_to_file(privacy,
255 encrypted_filename, sizeof(encrypted_filename),
256 msg, encrypted_mime);
257 if (r != MAIL_NO_ERROR) {
258 res = r;
259 goto err;
260 }
261
262 /* we are in a safe directory */
263
264 decrypted_f = mailprivacy_get_tmp_file(privacy,
265 decrypted_filename,
266 sizeof(decrypted_filename));
267 if (decrypted_f == NULL) {
268 res = MAIL_ERROR_FILE;
269 goto unlink_encrypted;
270 }
271 fclose(decrypted_f);
272
273 /* description */
274
275 description_f = mailprivacy_get_tmp_file(privacy,
276 description_filename,
277 sizeof(description_filename));
278 if (description_f == NULL) {
279 res = MAIL_ERROR_FILE;
280 goto unlink_decrypted;
281 }
282
283 fprintf(description_f, PGP_DECRYPT_DESCRIPTION);
284
285 /* get encryption key */
286
287 * default_key = '\0';
288 email = get_first_from_addr(mime);
289 if (email != NULL)
290 snprintf(default_key, sizeof(default_key),
291 "--default-key %s", email);
292
293 /* run the command */
294
295 r = mail_quote_filename(quoted_encrypted_filename,
296 sizeof(quoted_encrypted_filename), encrypted_filename);
297 if (r < 0) {
298 fclose(description_f);
299 res = MAIL_ERROR_MEMORY;
300 goto unlink_description;
301 }
302
303 r = mail_quote_filename(quoted_decrypted_filename,
304 sizeof(quoted_decrypted_filename), decrypted_filename);
305 if (r < 0) {
306 fclose(description_f);
307 res = MAIL_ERROR_MEMORY;
308 goto unlink_description;
309 }
310
311 decrypt_ok = 0;
312 snprintf(command, sizeof(command),
313 "gpg -q --batch --yes --out %s %s --decrypt %s",
314 quoted_decrypted_filename, default_key, quoted_encrypted_filename);
315
316 r = get_pgp_output(description_f, command);
317 switch (r) {
318 case NO_ERROR_PGP:
319 decrypt_ok = 1;
320 break;
321 case ERROR_PGP_CHECK:
322 decrypt_ok = 0;
323 break;
324 case ERROR_PGP_COMMAND:
325 fclose(description_f);
326 res = MAIL_ERROR_COMMAND;
327 goto unlink_description;
328 case ERROR_PGP_FILE:
329 fclose(description_f);
330 res = MAIL_ERROR_FILE;
331 goto unlink_description;
332 }
333 if (decrypt_ok)
334 fprintf(description_f, PGP_DECRYPT_SUCCESS);
335 else
336 fprintf(description_f, PGP_DECRYPT_FAILED);
337 fclose(description_f);
338
339 /* building multipart */
340
341 r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart);
342 if (r != MAILIMF_NO_ERROR) {
343 res = MAIL_ERROR_MEMORY;
344 goto unlink_description;
345 }
346
347 /* building the description part */
348
349 description_mime = mailprivacy_new_file_part(privacy,
350 description_filename,
351 "text/plain", MAILMIME_MECHANISM_8BIT);
352 if (description_mime == NULL) {
353 mailprivacy_mime_clear(multipart);
354 mailmime_free(multipart);
355 res = MAIL_ERROR_MEMORY;
356 goto unlink_description;
357 }
358
359 /* adds the description part */
360
361 r = mailmime_smart_add_part(multipart, description_mime);
362 if (r != MAIL_NO_ERROR) {
363 mailprivacy_mime_clear(description_mime);
364 mailmime_free(description_mime);
365 mailprivacy_mime_clear(multipart);
366 mailmime_free(multipart);
367 res = MAIL_ERROR_MEMORY;
368 goto unlink_description;
369 }
370
371 /* building the decrypted part */
372
373 r = mailprivacy_get_part_from_file(privacy, 1,
374 decrypted_filename, &decrypted_mime);
375 if (r == MAIL_NO_ERROR) {
376 /* adds the decrypted part */
377
378 r = mailmime_smart_add_part(multipart, decrypted_mime);
379 if (r != MAIL_NO_ERROR) {
380 mailprivacy_mime_clear(decrypted_mime);
381 mailmime_free(decrypted_mime);
382 mailprivacy_mime_clear(multipart);
383 mailmime_free(multipart);
384 res = MAIL_ERROR_MEMORY;
385 goto unlink_description;
386 }
387 }
388
389 unlink(description_filename);
390 unlink(decrypted_filename);
391 unlink(encrypted_filename);
392
393 * result = multipart;
394
395 return MAIL_NO_ERROR;
396
397 unlink_description:
398 unlink(description_filename);
399 unlink_decrypted:
400 unlink(decrypted_filename);
401 unlink_encrypted:
402 unlink(encrypted_filename);
403 err:
404 return res;
405}
406
407#define PGP_VERIFY_DESCRIPTION "PGP verify signed message\r\n"
408#define PGP_VERIFY_FAILED "PGP verification FAILED\r\n"
409#define PGP_VERIFY_SUCCESS "PGP verification success\r\n"
410
411static int
412pgp_verify(struct mailprivacy * privacy,
413 mailmessage * msg,
414 struct mailmime * mime, struct mailmime ** result)
415{
416 struct mailmime * signed_mime;
417 struct mailmime * signature_mime;
418 char signed_filename[PATH_MAX];
419 char signature_filename[PATH_MAX];
420 int res;
421 int r;
422 clistiter * cur;
423 char command[PATH_MAX];
424 int sign_ok;
425 struct mailmime * description_mime;
426 FILE * description_f;
427 char description_filename[PATH_MAX];
428 char quoted_signed_filename[PATH_MAX];
429 char quoted_signature_filename[PATH_MAX];
430 struct mailmime * multipart;
431 struct mailmime * signed_msg_mime;
432
433 /* get the two parts of the PGP message */
434
435 cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list);
436 if (cur == NULL) {
437 res = MAIL_ERROR_INVAL;
438 goto err;
439 }
440
441 signed_mime = clist_content(cur);
442 cur = clist_next(cur);
443 if (cur == NULL) {
444 res = MAIL_ERROR_INVAL;
445 goto err;
446 }
447
448 signature_mime = clist_content(cur);
449
450 /* fetch signed part and write it to a file */
451
452 r = mailprivacy_fetch_mime_body_to_file(privacy,
453 signed_filename, sizeof(signed_filename),
454 msg, signed_mime);
455 if (r != MAIL_NO_ERROR) {
456 res = r;
457 goto err;
458 }
459
460 /* fetch signed part and write it to a file */
461
462 r = mailprivacy_fetch_decoded_to_file(privacy,
463 signature_filename, sizeof(signature_filename),
464 msg, signature_mime);
465 if (r != MAIL_NO_ERROR) {
466 res = r;
467 goto unlink_signed;
468 }
469
470 /* description */
471
472 description_f = mailprivacy_get_tmp_file(privacy,
473 description_filename,
474 sizeof(description_filename));
475 if (description_f == NULL) {
476 res = MAIL_ERROR_FILE;
477 goto unlink_signature;
478 }
479
480 fprintf(description_f, PGP_VERIFY_DESCRIPTION);
481
482 /* run the command */
483
484 r = mail_quote_filename(quoted_signature_filename,
485 sizeof(quoted_signature_filename), signature_filename);
486 if (r < 0) {
487 fclose(description_f);
488 res = MAIL_ERROR_MEMORY;
489 goto unlink_description;
490 }
491
492 r = mail_quote_filename(quoted_signed_filename,
493 sizeof(quoted_signed_filename), signed_filename);
494 if (r < 0) {
495 fclose(description_f);
496 res = MAIL_ERROR_MEMORY;
497 goto unlink_description;
498 }
499
500 sign_ok = 0;
501 snprintf(command, sizeof(command), "gpg -q --batch --yes --verify %s %s",
502 quoted_signature_filename, quoted_signed_filename);
503
504 r = get_pgp_output(description_f, command);
505 switch (r) {
506 case NO_ERROR_PGP:
507 sign_ok = 1;
508 break;
509 case ERROR_PGP_CHECK:
510 sign_ok = 0;
511 break;
512 case ERROR_PGP_COMMAND:
513 fclose(description_f);
514 res = MAIL_ERROR_COMMAND;
515 goto unlink_description;
516 case ERROR_PGP_FILE:
517 fclose(description_f);
518 res = MAIL_ERROR_FILE;
519 goto unlink_description;
520 }
521
522 if (sign_ok)
523 fprintf(description_f, PGP_VERIFY_SUCCESS);
524 else
525 fprintf(description_f, PGP_VERIFY_FAILED);
526 fclose(description_f);
527
528 /* building multipart */
529
530 r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart);
531 if (r != MAILIMF_NO_ERROR) {
532 res = MAIL_ERROR_MEMORY;
533 goto unlink_description;
534 }
535
536 /* building the description part */
537
538 description_mime = mailprivacy_new_file_part(privacy,
539 description_filename,
540 "text/plain", MAILMIME_MECHANISM_8BIT);
541 if (description_mime == NULL) {
542 mailprivacy_mime_clear(multipart);
543 mailmime_free(multipart);
544 res = MAIL_ERROR_MEMORY;
545 goto unlink_description;
546 }
547
548 /* adds the description part */
549
550 r = mailmime_smart_add_part(multipart, description_mime);
551 if (r != MAIL_NO_ERROR) {
552 mailprivacy_mime_clear(description_mime);
553 mailmime_free(description_mime);
554 mailprivacy_mime_clear(multipart);
555 mailmime_free(multipart);
556 res = MAIL_ERROR_MEMORY;
557 goto unlink_description;
558 }
559
560 r = mailprivacy_get_part_from_file(privacy, 1,
561 signed_filename, &signed_msg_mime);
562 if (r != MAIL_NO_ERROR) {
563 mailprivacy_mime_clear(multipart);
564 mailmime_free(multipart);
565 res = MAIL_ERROR_MEMORY;
566 goto unlink_description;
567 }
568
569 r = mailmime_smart_add_part(multipart, signed_msg_mime);
570 if (r != MAIL_NO_ERROR) {
571 mailprivacy_mime_clear(signed_msg_mime);
572 mailmime_free(signed_msg_mime);
573 mailprivacy_mime_clear(multipart);
574 mailmime_free(multipart);
575 res = MAIL_ERROR_MEMORY;
576 goto unlink_description;
577 }
578
579 unlink(description_filename);
580 unlink(signature_filename);
581 unlink(signed_filename);
582
583 * result = multipart;
584
585 return MAIL_NO_ERROR;
586
587 unlink_description:
588 unlink(description_filename);
589 unlink_signature:
590 unlink(signature_filename);
591 unlink_signed:
592 unlink(signed_filename);
593 err:
594 return res;
595}
596
597
598#define PGP_CLEAR_VERIFY_DESCRIPTION "PGP verify clear signed message\r\n"
599#define PGP_CLEAR_VERIFY_FAILED "PGP verification FAILED\r\n"
600#define PGP_CLEAR_VERIFY_SUCCESS "PGP verification success\r\n"
601
602static int pgp_verify_clearsigned(struct mailprivacy * privacy,
603 mailmessage * msg,
604 struct mailmime * mime,
605 char * content, size_t content_len, struct mailmime ** result)
606{
607 int r;
608 char command[PATH_MAX];
609 int res;
610 int sign_ok;
611 size_t written;
612 char signed_filename[PATH_MAX];
613 FILE * signed_f;
614 char stripped_filename[PATH_MAX];
615 FILE * stripped_f;
616 char description_filename[PATH_MAX];
617 FILE * description_f;
618 char quoted_signed_filename[PATH_MAX];
619 char quoted_stripped_filename[PATH_MAX];
620 struct mailmime * stripped_mime;
621 struct mailmime * description_mime;
622 struct mailmime * multipart;
623 struct mailmime_content * content_type;
624
625 if (mime->mm_parent == NULL) {
626 res = MAIL_ERROR_INVAL;
627 goto err;
628 }
629
630 if (mime->mm_parent->mm_type == MAILMIME_SINGLE) {
631 res = MAIL_ERROR_INVAL;
632 goto err;
633 }
634
635 signed_f = mailprivacy_get_tmp_file(privacy,
636 signed_filename, sizeof(signed_filename));
637 if (signed_f == NULL) {
638 res = MAIL_ERROR_FILE;
639 goto err;
640 }
641
642 written = fwrite(content, 1, content_len, signed_f);
643 if (written != content_len) {
644 fclose(signed_f);
645 unlink(signed_filename);
646 res = MAIL_ERROR_FILE;
647 goto err;
648 }
649 fclose(signed_f);
650
651 /* XXX - prepare file for PGP, remove trailing WS */
652
653 stripped_f = mailprivacy_get_tmp_file(privacy,
654 stripped_filename, sizeof(stripped_filename));
655 if (stripped_f == NULL) {
656 res = MAIL_ERROR_FILE;
657 goto unlink_signed;
658 }
659 fclose(stripped_f);
660
661 /* description */
662
663 description_f = mailprivacy_get_tmp_file(privacy,
664 description_filename,
665 sizeof(description_filename));
666 if (description_f == NULL) {
667 res = MAIL_ERROR_FILE;
668 goto unlink_stripped;
669 }
670
671 fprintf(description_f, PGP_CLEAR_VERIFY_DESCRIPTION);
672
673 r = mail_quote_filename(quoted_stripped_filename,
674 sizeof(quoted_stripped_filename), stripped_filename);
675 if (r < 0) {
676 fclose(description_f);
677 res = MAIL_ERROR_MEMORY;
678 goto unlink_description;
679 }
680
681 r = mail_quote_filename(quoted_signed_filename,
682 sizeof(quoted_signed_filename), signed_filename);
683 if (r < 0) {
684 fclose(description_f);
685 res = MAIL_ERROR_MEMORY;
686 goto unlink_description;
687 }
688
689 snprintf(command, sizeof(command),
690 "gpg -q --batch --yes --out %s --decrypt %s",
691 quoted_stripped_filename, quoted_signed_filename);
692
693 sign_ok = 0;
694 r = get_pgp_output(description_f, command);
695 switch (r) {
696 case NO_ERROR_PGP:
697 sign_ok = 1;
698 break;
699 case ERROR_PGP_CHECK:
700 sign_ok = 0;
701 break;
702 case ERROR_PGP_COMMAND:
703 res = MAIL_ERROR_COMMAND;
704 fclose(description_f);
705 goto unlink_description;
706 case ERROR_PGP_FILE:
707 res = MAIL_ERROR_FILE;
708 fclose(description_f);
709 goto unlink_description;
710 }
711 if (sign_ok)
712 fprintf(description_f, PGP_CLEAR_VERIFY_SUCCESS);
713 else
714 fprintf(description_f, PGP_CLEAR_VERIFY_FAILED);
715 fclose(description_f);
716
717 /* building multipart */
718
719 r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart);
720 if (r != MAILIMF_NO_ERROR) {
721 res = MAIL_ERROR_MEMORY;
722 goto unlink_description;
723 }
724
725 /* building the description part */
726
727 description_mime = mailprivacy_new_file_part(privacy,
728 description_filename,
729 "text/plain", MAILMIME_MECHANISM_8BIT);
730 if (description_mime == NULL) {
731 mailprivacy_mime_clear(multipart);
732 mailmime_free(multipart);
733 res = MAIL_ERROR_MEMORY;
734 goto unlink_description;
735 }
736
737 /* adds the description part */
738
739 r = mailmime_smart_add_part(multipart, description_mime);
740 if (r != MAIL_NO_ERROR) {
741 mailprivacy_mime_clear(description_mime);
742 mailmime_free(description_mime);
743 mailprivacy_mime_clear(multipart);
744 mailmime_free(multipart);
745 res = MAIL_ERROR_MEMORY;
746 goto unlink_description;
747 }
748
749 /* building the signature stripped part */
750
751 stripped_mime = mailprivacy_new_file_part(privacy,
752 stripped_filename,
753 "application/octet-stream",
754 MAILMIME_MECHANISM_8BIT);
755 if (stripped_mime == NULL) {
756 mailprivacy_mime_clear(multipart);
757 mailmime_free(multipart);
758 res = MAIL_ERROR_MEMORY;
759 goto unlink_description;
760 }
761
762 /* place original content type */
763
764 content_type = mailmime_content_dup(mime->mm_content_type);
765 if (content_type == NULL) {
766 mailprivacy_mime_clear(stripped_mime);
767 mailmime_free(stripped_mime);
768 mailprivacy_mime_clear(multipart);
769 mailmime_free(multipart);
770 res = MAIL_ERROR_MEMORY;
771 goto unlink_description;
772 }
773
774 mailmime_content_free(stripped_mime->mm_content_type);
775 stripped_mime->mm_content_type = content_type;
776
777 /* place original MIME fields */
778
779 if (mime->mm_mime_fields != NULL) {
780 struct mailmime_fields * mime_fields;
781 clistiter * cur;
782
783 mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields);
784 if (mime_fields == NULL) {
785 mailprivacy_mime_clear(stripped_mime);
786 mailmime_free(stripped_mime);
787 mailprivacy_mime_clear(multipart);
788 mailmime_free(multipart);
789 res = MAIL_ERROR_MEMORY;
790 goto unlink_description;
791 }
792 for(cur = clist_begin(mime_fields->fld_list) ;
793 cur != NULL ; cur = clist_next(cur)) {
794 struct mailmime_field * field;
795
796 field = clist_content(cur);
797 if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) {
798 mailmime_field_free(field);
799 clist_delete(mime_fields->fld_list, cur);
800 break;
801 }
802 }
803 clist_concat(stripped_mime->mm_mime_fields->fld_list,
804 mime_fields->fld_list);
805 mailmime_fields_free(mime_fields);
806 }
807
808 /* adds the stripped part */
809
810 r = mailmime_smart_add_part(multipart, stripped_mime);
811 if (r != MAIL_NO_ERROR) {
812 mailprivacy_mime_clear(stripped_mime);
813 mailmime_free(stripped_mime);
814 mailprivacy_mime_clear(multipart);
815 mailmime_free(multipart);
816 res = MAIL_ERROR_MEMORY;
817 goto unlink_description;
818 }
819
820 unlink(description_filename);
821 unlink(stripped_filename);
822 unlink(signed_filename);
823
824 * result = multipart;
825
826 return MAIL_NO_ERROR;
827
828 unlink_description:
829 unlink(description_filename);
830 unlink_stripped:
831 unlink(stripped_filename);
832 unlink_signed:
833 unlink(signed_filename);
834 err:
835 return res;
836}
837
838
839#define PGP_DECRYPT_ARMOR_DESCRIPTION "PGP ASCII armor encrypted part\r\n"
840#define PGP_DECRYPT_ARMOR_FAILED "PGP ASCII armor decryption FAILED\r\n"
841#define PGP_DECRYPT_ARMOR_SUCCESS "PGP ASCII armor decryption success\r\n"
842
843static int pgp_decrypt_armor(struct mailprivacy * privacy,
844 mailmessage * msg,
845 struct mailmime * mime,
846 char * content, size_t content_len, struct mailmime ** result)
847{
848 char default_key[PATH_MAX];
849 FILE * encrypted_f;
850 char encrypted_filename[PATH_MAX];
851 char description_filename[PATH_MAX];
852 FILE * description_f;
853 char decrypted_filename[PATH_MAX];
854 FILE * decrypted_f;
855 size_t written;
856 char command[PATH_MAX];
857 struct mailmime * description_mime;
858 struct mailmime * decrypted_mime;
859 struct mailmime * multipart;
860 int r;
861 int res;
862 int sign_ok;
863 char quoted_decrypted_filename[PATH_MAX];
864 char quoted_encrypted_filename[PATH_MAX];
865 char * email;
866
867 if (mime->mm_parent == NULL) {
868 res = MAIL_ERROR_INVAL;
869 goto err;
870 }
871
872 if (mime->mm_parent->mm_type == MAILMIME_SINGLE) {
873 res = MAIL_ERROR_INVAL;
874 goto err;
875 }
876
877 encrypted_f = mailprivacy_get_tmp_file(privacy,
878 encrypted_filename,
879 sizeof(encrypted_filename));
880 if (encrypted_f == NULL) {
881 res = MAIL_ERROR_FILE;
882 goto err;
883 }
884
885 written = fwrite(content, 1, content_len, encrypted_f);
886 if (written != content_len) {
887 fclose(encrypted_f);
888 unlink(encrypted_filename);
889 res = MAIL_ERROR_FILE;
890 goto err;
891 }
892
893 fclose(encrypted_f);
894
895 /* we are in a safe directory */
896
897 decrypted_f = mailprivacy_get_tmp_file(privacy,
898 decrypted_filename,
899 sizeof(decrypted_filename));
900 if (decrypted_f == NULL) {
901 res = MAIL_ERROR_FILE;
902 goto unlink_encrypted;
903 }
904 fclose(decrypted_f);
905
906 /* description */
907
908 description_f = mailprivacy_get_tmp_file(privacy,
909 description_filename,
910 sizeof(description_filename));
911 if (description_f == NULL) {
912 res = MAIL_ERROR_FILE;
913 goto unlink_decrypted;
914 }
915
916 fprintf(description_f, PGP_DECRYPT_ARMOR_DESCRIPTION);
917
918 /* get encryption key */
919
920 * default_key = '\0';
921 email = get_first_from_addr(mime);
922 if (email != NULL)
923 snprintf(default_key, sizeof(default_key),
924 "--default-key %s", email);
925
926 /* run the command */
927
928 r = mail_quote_filename(quoted_encrypted_filename,
929 sizeof(quoted_encrypted_filename), encrypted_filename);
930 if (r < 0) {
931 fclose(description_f);
932 res = MAIL_ERROR_MEMORY;
933 goto unlink_description;
934 }
935
936 r = mail_quote_filename(quoted_decrypted_filename,
937 sizeof(quoted_decrypted_filename), decrypted_filename);
938 if (r < 0) {
939 fclose(description_f);
940 res = MAIL_ERROR_MEMORY;
941 goto unlink_description;
942 }
943
944 sign_ok = 0;
945 snprintf(command, sizeof(command),
946 "gpg -q --batch --yes --out %s %s --decrypt %s",
947 quoted_decrypted_filename, default_key, quoted_encrypted_filename);
948
949 r = get_pgp_output(description_f, command);
950 switch (r) {
951 case NO_ERROR_PGP:
952 sign_ok = 1;
953 break;
954 case ERROR_PGP_CHECK:
955 sign_ok = 0;
956 break;
957 case ERROR_PGP_COMMAND:
958 fclose(description_f);
959 res = MAIL_ERROR_COMMAND;
960 goto unlink_description;
961 case ERROR_PGP_FILE:
962 fclose(description_f);
963 res = MAIL_ERROR_FILE;
964 goto unlink_description;
965 }
966 if (sign_ok)
967 fprintf(description_f, PGP_DECRYPT_ARMOR_SUCCESS);
968 else
969 fprintf(description_f, PGP_DECRYPT_ARMOR_FAILED);
970 fclose(description_f);
971
972 /* building multipart */
973
974 r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart);
975 if (r != MAILIMF_NO_ERROR) {
976 res = MAIL_ERROR_MEMORY;
977 goto unlink_description;
978 }
979
980 /* building the description part */
981
982 description_mime = mailprivacy_new_file_part(privacy,
983 description_filename,
984 "text/plain", MAILMIME_MECHANISM_8BIT);
985 if (description_mime == NULL) {
986 mailprivacy_mime_clear(multipart);
987 mailmime_free(multipart);
988 res = MAIL_ERROR_MEMORY;
989 goto unlink_description;
990 }
991
992 /* adds the description part */
993
994 r = mailmime_smart_add_part(multipart, description_mime);
995 if (r != MAIL_NO_ERROR) {
996 mailprivacy_mime_clear(description_mime);
997 mailmime_free(description_mime);
998 mailprivacy_mime_clear(multipart);
999 mailmime_free(multipart);
1000 res = MAIL_ERROR_MEMORY;
1001 goto unlink_description;
1002 }
1003
1004 /* building the decrypted part */
1005
1006 r = mailprivacy_get_part_from_file(privacy, 1,
1007 decrypted_filename, &decrypted_mime);
1008 if (r != MAIL_NO_ERROR) {
1009 mailprivacy_mime_clear(multipart);
1010 mailmime_free(multipart);
1011 res = r;
1012 goto unlink_description;
1013 }
1014
1015 /* adds the decrypted part */
1016
1017 r = mailmime_smart_add_part(multipart, decrypted_mime);
1018 if (r != MAIL_NO_ERROR) {
1019 mailprivacy_mime_clear(decrypted_mime);
1020 mailmime_free(decrypted_mime);
1021 mailprivacy_mime_clear(multipart);
1022 mailmime_free(multipart);
1023 res = MAIL_ERROR_MEMORY;
1024 goto unlink_description;
1025 }
1026
1027 unlink(description_filename);
1028 unlink(decrypted_filename);
1029 unlink(encrypted_filename);
1030
1031 * result = multipart;
1032
1033 return MAIL_NO_ERROR;
1034
1035 unlink_description:
1036 unlink(description_filename);
1037 unlink_decrypted:
1038 unlink(decrypted_filename);
1039 unlink_encrypted:
1040 unlink(encrypted_filename);
1041 err:
1042 return res;
1043}
1044
1045
1046static int mime_is_text(struct mailmime * build_info)
1047{
1048 if (build_info->mm_type == MAILMIME_SINGLE) {
1049 if (build_info->mm_content_type != NULL) {
1050 if (build_info->mm_content_type->ct_type->tp_type ==
1051 MAILMIME_TYPE_DISCRETE_TYPE) {
1052 if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type ==
1053 MAILMIME_DISCRETE_TYPE_TEXT)
1054 return 1;
1055 }
1056 }
1057 else
1058 return 1;
1059 }
1060
1061 return 0;
1062}
1063
1064
1065static int pgp_test_encrypted(struct mailprivacy * privacy,
1066 mailmessage * msg, struct mailmime * mime)
1067{
1068 int r;
1069 int res;
1070
1071 switch (mime->mm_type) {
1072 case MAILMIME_MULTIPLE:
1073 return (pgp_is_encrypted(mime) || pgp_is_signed(mime));
1074
1075 case MAILMIME_SINGLE:
1076 /* clear sign or ASCII armor encryption */
1077 if (mime_is_text(mime)) {
1078 char * content;
1079 size_t content_len;
1080 char * parsed_content;
1081 size_t parsed_content_len;
1082 size_t cur_token;
1083 int encoding;
1084 struct mailmime_single_fields single_fields;
1085
1086 r = mailprivacy_msg_fetch_section(privacy, msg, mime,
1087 &content, &content_len);
1088 if (r != MAIL_NO_ERROR)
1089 return 0;
1090
1091 mailmime_single_fields_init(&single_fields, mime->mm_mime_fields,
1092 mime->mm_content_type);
1093 if (single_fields.fld_encoding != NULL)
1094 encoding = single_fields.fld_encoding->enc_type;
1095 else
1096 encoding = MAILMIME_MECHANISM_8BIT;
1097
1098 cur_token = 0;
1099 r = mailmime_part_parse(content, content_len, &cur_token,
1100 encoding, &parsed_content, &parsed_content_len);
1101 mailprivacy_msg_fetch_result_free(privacy, msg, content);
1102
1103 if (r != MAILIMF_NO_ERROR)
1104 return 0;
1105
1106 res = 0;
1107
1108 if (pgp_is_clearsigned(parsed_content, parsed_content_len))
1109 res = 1;
1110 else if (pgp_is_crypted_armor(parsed_content, parsed_content_len))
1111 res = 1;
1112
1113 mmap_string_unref(parsed_content);
1114
1115 return res;
1116 }
1117 break;
1118 }
1119
1120 return 0;
1121}
1122
1123static int pgp_handler(struct mailprivacy * privacy,
1124 mailmessage * msg,
1125 struct mailmime * mime, struct mailmime ** result)
1126{
1127 int r;
1128 struct mailmime * alternative_mime;
1129
1130 alternative_mime = NULL;
1131 switch (mime->mm_type) {
1132 case MAILMIME_MULTIPLE:
1133 r = MAIL_ERROR_INVAL;
1134 if (pgp_is_encrypted(mime)) {
1135 r = pgp_decrypt(privacy, msg, mime, &alternative_mime);
1136 }
1137 else if (pgp_is_signed(mime)) {
1138 r = pgp_verify(privacy, msg, mime, &alternative_mime);
1139 }
1140
1141 if (r != MAIL_NO_ERROR)
1142 return r;
1143
1144 * result = alternative_mime;
1145
1146 return MAIL_NO_ERROR;
1147
1148 case MAILMIME_SINGLE:
1149 /* clear sign or ASCII armor encryption */
1150 if (mime_is_text(mime)) {
1151 char * content;
1152 size_t content_len;
1153 char * parsed_content;
1154 size_t parsed_content_len;
1155 size_t cur_token;
1156 int encoding;
1157 struct mailmime_single_fields single_fields;
1158
1159 r = mailprivacy_msg_fetch_section(privacy, msg, mime,
1160 &content, &content_len);
1161 if (r != MAIL_NO_ERROR)
1162 return MAIL_ERROR_FETCH;
1163
1164 mailmime_single_fields_init(&single_fields, mime->mm_mime_fields,
1165 mime->mm_content_type);
1166 if (single_fields.fld_encoding != NULL)
1167 encoding = single_fields.fld_encoding->enc_type;
1168 else
1169 encoding = MAILMIME_MECHANISM_8BIT;
1170
1171 cur_token = 0;
1172 r = mailmime_part_parse(content, content_len, &cur_token,
1173 encoding, &parsed_content, &parsed_content_len);
1174 mailprivacy_msg_fetch_result_free(privacy, msg, content);
1175
1176 if (r != MAILIMF_NO_ERROR)
1177 return MAIL_ERROR_PARSE;
1178
1179 r = MAIL_ERROR_INVAL;
1180 if (pgp_is_clearsigned(parsed_content,
1181 parsed_content_len)) {
1182 r = pgp_verify_clearsigned(privacy,
1183 msg, mime, parsed_content, parsed_content_len, &alternative_mime);
1184 }
1185 else if (pgp_is_crypted_armor(parsed_content,
1186 parsed_content_len)) {
1187 r = pgp_decrypt_armor(privacy,
1188 msg, mime, parsed_content, parsed_content_len, &alternative_mime);
1189 }
1190
1191 mmap_string_unref(parsed_content);
1192
1193 if (r != MAIL_NO_ERROR)
1194 return r;
1195
1196 * result = alternative_mime;
1197
1198 return MAIL_NO_ERROR;
1199 }
1200 break;
1201 }
1202
1203 return MAIL_ERROR_INVAL;
1204}
1205
1206
1207#if 0
1208static void prepare_mime_single(struct mailmime * mime)
1209{
1210 struct mailmime_single_fields single_fields;
1211 int encoding;
1212 int r;
1213
1214 if (mime->mime_fields != NULL) {
1215 mailmime_single_fields_init(&single_fields, mime->mime_fields,
1216 mime->content_type);
1217 if (single_fields.encoding != NULL) {
1218 encoding = single_fields.encoding->type;
1219 switch (encoding) {
1220 case MAILMIME_MECHANISM_8BIT:
1221 case MAILMIME_MECHANISM_7BIT:
1222 case MAILMIME_MECHANISM_BINARY:
1223 single_fields.encoding->type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
1224 break;
1225 }
1226 }
1227 else {
1228 struct mailmime_mechanism * mechanism;
1229 struct mailmime_field * field;
1230
1231 mechanism =
1232 mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL);
1233 if (mechanism == NULL)
1234 return;
1235
1236 field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING,
1237 NULL, mechanism, NULL, NULL, 0, NULL, NULL);
1238 if (field == NULL) {
1239 mailmime_mechanism_free(mechanism);
1240 return;
1241 }
1242
1243 r = clist_append(mime->mime_fields->list, field);
1244 if (r < 0) {
1245 mailmime_field_free(field);
1246 return;
1247 }
1248 }
1249 }
1250
1251 switch (mime->body->encoding) {
1252 case MAILMIME_MECHANISM_8BIT:
1253 case MAILMIME_MECHANISM_7BIT:
1254 case MAILMIME_MECHANISM_BINARY:
1255 mime->body->encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
1256 mime->body->encoded = 0;
1257 break;
1258 }
1259}
1260
1261/*
1262 prepare_mime()
1263
1264 we assume we built ourself the message.
1265*/
1266
1267static void prepare_mime(struct mailmime * mime)
1268{
1269 clistiter * cur;
1270
1271 switch (mime->type) {
1272 case MAILMIME_SINGLE:
1273 if (mime->body != NULL) {
1274 prepare_mime_single(mime);
1275 }
1276 break;
1277
1278 case MAILMIME_MULTIPLE:
1279 for(cur = clist_begin(mime->list) ; cur != NULL ; cur = clist_next(cur)) {
1280 struct mailmime * child;
1281
1282 child = cur->data;
1283
1284 prepare_mime(child);
1285 }
1286 break;
1287
1288 case MAILMIME_MESSAGE:
1289 if (mime->msg_mime) {
1290 prepare_mime(mime->msg_mime);
1291 }
1292 break;
1293 }
1294}
1295#endif
1296
1297static int pgp_sign_mime(struct mailprivacy * privacy,
1298 struct mailmime * mime, struct mailmime ** result)
1299{
1300 char signed_filename[PATH_MAX];
1301 FILE * signed_f;
1302 int res;
1303 int r;
1304 int col;
1305 char signature_filename[PATH_MAX];
1306 FILE * signature_f;
1307 char command[PATH_MAX];
1308 char quoted_signature_filename[PATH_MAX];
1309 char quoted_signed_filename[PATH_MAX];
1310 char default_key[PATH_MAX];
1311 struct mailmime * signature_mime;
1312 struct mailmime * multipart;
1313 struct mailmime_content * content;
1314 struct mailmime_parameter * param;
1315 struct mailmime * signed_msg_mime;
1316 char * dup_signature_filename;
1317 char * email;
1318
1319 /* get signing key */
1320
1321 * default_key = '\0';
1322 email = get_first_from_addr(mime);
1323 if (email != NULL)
1324 snprintf(default_key, sizeof(default_key),
1325 "--default-key %s", email);
1326
1327 /* part to sign */
1328
1329 /* encode quoted printable all text parts */
1330
1331 mailprivacy_prepare_mime(mime);
1332
1333 signed_f = mailprivacy_get_tmp_file(privacy,
1334 signed_filename, sizeof(signed_filename));
1335 if (signed_f == NULL) {
1336 res = MAIL_ERROR_FILE;
1337 goto err;
1338 }
1339
1340 col = 0;
1341 r = mailmime_write(signed_f, &col, mime);
1342 if (r != MAILIMF_NO_ERROR) {
1343 fclose(signed_f);
1344 res = MAIL_ERROR_FILE;
1345 goto unlink_signed;
1346 }
1347
1348 fclose(signed_f);
1349
1350 /* prepare destination file for signature */
1351
1352 signature_f = mailprivacy_get_tmp_file(privacy,
1353 signature_filename,
1354 sizeof(signature_filename));
1355 if (signature_f == NULL) {
1356 res = MAIL_ERROR_FILE;
1357 goto unlink_signed;
1358 }
1359 fclose(signature_f);
1360
1361 r = mail_quote_filename(quoted_signed_filename,
1362 sizeof(quoted_signed_filename), signed_filename);
1363 if (r < 0) {
1364 res = MAIL_ERROR_MEMORY;
1365 goto unlink_signature;
1366 }
1367
1368 r = mail_quote_filename(quoted_signature_filename,
1369 sizeof(quoted_signature_filename), signature_filename);
1370 if (r < 0) {
1371 res = MAIL_ERROR_MEMORY;
1372 goto unlink_signature;
1373 }
1374
1375 snprintf(command, sizeof(command),
1376 "gpg -q -a --batch --yes --digest-algo sha1 --out %s %s -b %s 2>/dev/null",
1377 quoted_signature_filename, default_key, quoted_signed_filename);
1378
1379 r = system(command);
1380 if (WEXITSTATUS(r) != 0) {
1381 res = MAIL_ERROR_COMMAND;
1382 goto unlink_signature;
1383 }
1384
1385 /* multipart */
1386
1387 multipart = mailprivacy_new_file_part(privacy, NULL,
1388 "multipart/signed", -1);
1389
1390 content = multipart->mm_content_type;
1391
1392 param = mailmime_param_new_with_data("micalg", "pgp-sha1");
1393 if (param == NULL) {
1394 mailmime_free(multipart);
1395 res = MAIL_ERROR_MEMORY;
1396 goto unlink_signature;
1397 }
1398
1399 r = clist_append(content->ct_parameters, param);
1400 if (r < 0) {
1401 mailmime_parameter_free(param);
1402 mailmime_free(multipart);
1403 res = MAIL_ERROR_MEMORY;
1404 goto unlink_signature;
1405 }
1406
1407 param = mailmime_param_new_with_data("protocol",
1408 "application/pgp-signature");
1409 if (param == NULL) {
1410 mailmime_free(multipart);
1411 res = MAIL_ERROR_MEMORY;
1412 goto unlink_signature;
1413 }
1414
1415 r = clist_append(content->ct_parameters, param);
1416 if (r < 0) {
1417 mailmime_parameter_free(param);
1418 mailmime_free(multipart);
1419 res = MAIL_ERROR_MEMORY;
1420 goto unlink_signature;
1421 }
1422
1423 /* signed part */
1424
1425 r = mailprivacy_get_part_from_file(privacy, 1,
1426 signed_filename, &signed_msg_mime);
1427 if (r != MAIL_NO_ERROR) {
1428 mailprivacy_mime_clear(multipart);
1429 mailmime_free(multipart);
1430 res = r;
1431 goto unlink_signature;
1432 }
1433
1434 mailprivacy_prepare_mime(signed_msg_mime);
1435
1436 r = mailmime_smart_add_part(multipart, signed_msg_mime);
1437 if (r != MAIL_NO_ERROR) {
1438 mailprivacy_mime_clear(signed_msg_mime);
1439 mailmime_free(signed_msg_mime);
1440 mailprivacy_mime_clear(multipart);
1441 mailmime_free(multipart);
1442 res = MAIL_ERROR_MEMORY;
1443 goto unlink_signature;
1444 }
1445
1446 /* signature part */
1447
1448 /* reencode the signature file with CRLF */
1449 dup_signature_filename = mailprivacy_dup_imf_file(privacy,
1450 signature_filename);
1451 if (dup_signature_filename == NULL) {
1452 mailprivacy_mime_clear(multipart);
1453 mailmime_free(multipart);
1454 res = MAIL_ERROR_FILE;
1455 goto unlink_signature;
1456 }
1457
1458 /* replace the signature file */
1459 unlink(signature_filename);
1460 strncpy(signature_filename,
1461 dup_signature_filename, sizeof(signature_filename));
1462 signature_filename[sizeof(signature_filename) - 1] = '\0';
1463
1464 signature_mime = mailprivacy_new_file_part(privacy,
1465 signature_filename,
1466 "application/pgp-signature",
1467 MAILMIME_MECHANISM_8BIT);
1468 if (signature_mime == NULL) {
1469 mailprivacy_mime_clear(multipart);
1470 mailmime_free(multipart);
1471 res = MAIL_ERROR_MEMORY;
1472 goto unlink_signature;
1473 }
1474
1475 r = mailmime_smart_add_part(multipart, signature_mime);
1476 if (r != MAIL_NO_ERROR) {
1477 mailprivacy_mime_clear(signature_mime);
1478 mailmime_free(signature_mime);
1479 mailprivacy_mime_clear(multipart);
1480 mailmime_free(multipart);
1481 res = MAIL_ERROR_MEMORY;
1482 goto unlink_signature;
1483 }
1484
1485 unlink(signature_filename);
1486 unlink(signed_filename);
1487
1488 * result = multipart;
1489
1490 return MAIL_NO_ERROR;
1491
1492 unlink_signature:
1493 unlink(signature_filename);
1494 unlink_signed:
1495 unlink(signed_filename);
1496 err:
1497 return res;
1498}
1499
1500
1501/* ********************************************************************* */
1502/* find GPG recipient */
1503
1504static int recipient_add_mb(char * recipient, size_t * len,
1505 struct mailimf_mailbox * mb)
1506{
1507 char buffer[PATH_MAX];
1508 size_t buflen;
1509
1510 if (mb->mb_addr_spec != NULL) {
1511 snprintf(buffer, sizeof(buffer), "-r %s ", mb->mb_addr_spec);
1512 buflen = strlen(buffer);
1513 if (buflen >= * len)
1514 return MAIL_ERROR_MEMORY;
1515
1516 strncat(recipient, buffer, * len);
1517 (* len) -= buflen;
1518 }
1519
1520 return MAIL_NO_ERROR;
1521}
1522
1523static int recipient_add_mb_list(char * recipient, size_t * len,
1524 struct mailimf_mailbox_list * mb_list)
1525{
1526 clistiter * cur;
1527 int r;
1528
1529 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1530 cur = clist_next(cur)) {
1531 struct mailimf_mailbox * mb;
1532
1533 mb = clist_content(cur);
1534
1535 r = recipient_add_mb(recipient, len, mb);
1536 if (r != MAIL_NO_ERROR)
1537 return r;
1538 }
1539
1540 return MAIL_NO_ERROR;
1541}
1542
1543static int recipient_add_group(char * recipient, size_t * len,
1544 struct mailimf_group * group)
1545{
1546 return recipient_add_mb_list(recipient, len, group->grp_mb_list);
1547}
1548
1549static int recipient_add_addr(char * recipient, size_t * len,
1550 struct mailimf_address * addr)
1551{
1552 int r;
1553
1554 switch (addr->ad_type) {
1555 case MAILIMF_ADDRESS_MAILBOX:
1556 r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox);
1557 break;
1558 case MAILIMF_ADDRESS_GROUP:
1559 r = recipient_add_group(recipient, len, addr->ad_data.ad_group);
1560 break;
1561 default:
1562 r = MAIL_ERROR_INVAL;
1563 }
1564
1565 return r;
1566}
1567
1568static int recipient_add_addr_list(char * recipient, size_t * len,
1569 struct mailimf_address_list * addr_list)
1570{
1571 clistiter * cur;
1572 int r;
1573
1574 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1575 cur = clist_next(cur)) {
1576 struct mailimf_address * addr;
1577
1578 addr = clist_content(cur);
1579
1580 r = recipient_add_addr(recipient, len, addr);
1581 if (r != MAIL_NO_ERROR)
1582 return r;
1583 }
1584
1585 return MAIL_NO_ERROR;
1586}
1587
1588
1589static int collect_recipient(char * recipient, size_t size,
1590 struct mailimf_fields * fields)
1591{
1592 struct mailimf_single_fields single_fields;
1593 int r;
1594 size_t remaining;
1595 int res;
1596
1597 * recipient = '\0';
1598 remaining = size;
1599
1600 if (fields != NULL)
1601 mailimf_single_fields_init(&single_fields, fields);
1602
1603 if (single_fields.fld_to != NULL) {
1604 r = recipient_add_addr_list(recipient, &remaining,
1605 single_fields.fld_to->to_addr_list);
1606 if (r != MAIL_NO_ERROR) {
1607 res = r;
1608 goto err;
1609 }
1610 }
1611
1612 if (single_fields.fld_cc != NULL) {
1613 r = recipient_add_addr_list(recipient, &remaining,
1614 single_fields.fld_cc->cc_addr_list);
1615 if (r != MAIL_NO_ERROR) {
1616 res = r;
1617 goto err;
1618 }
1619 }
1620
1621 if (single_fields.fld_bcc != NULL) {
1622 if (single_fields.fld_bcc->bcc_addr_list != NULL) {
1623 r = recipient_add_addr_list(recipient, &remaining,
1624 single_fields.fld_bcc->bcc_addr_list);
1625 if (r != MAIL_NO_ERROR) {
1626 res = r;
1627 goto err;
1628 }
1629 }
1630 }
1631
1632 return MAIL_NO_ERROR;
1633
1634 err:
1635 return res;
1636}
1637
1638
1639#define PGP_VERSION "Version: 1\r\n"
1640
1641static int pgp_sign_encrypt_mime(struct mailprivacy * privacy,
1642 struct mailmime * mime, struct mailmime ** result)
1643{
1644 char original_filename[PATH_MAX];
1645 FILE * original_f;
1646 int res;
1647 int r;
1648 int col;
1649 char encrypted_filename[PATH_MAX];
1650 FILE * encrypted_f;
1651 char version_filename[PATH_MAX];
1652 FILE * version_f;
1653 char command[PATH_MAX];
1654 char quoted_original_filename[PATH_MAX];
1655 char quoted_encrypted_filename[PATH_MAX];
1656 char default_key[PATH_MAX];
1657 struct mailmime * version_mime;
1658 struct mailmime * multipart;
1659 struct mailmime_content * content;
1660 struct mailmime_parameter * param;
1661 struct mailmime * encrypted_mime;
1662 char recipient[PATH_MAX];
1663 struct mailimf_fields * fields;
1664 struct mailmime * root;
1665 size_t written;
1666 char * email;
1667
1668 root = mime;
1669 while (root->mm_parent != NULL)
1670 root = root->mm_parent;
1671
1672 fields = NULL;
1673 if (root->mm_type == MAILMIME_MESSAGE)
1674 fields = root->mm_data.mm_message.mm_fields;
1675
1676 /* recipient */
1677
1678 collect_recipient(recipient, sizeof(recipient), fields);
1679
1680 /* get signing key */
1681
1682 * default_key = '\0';
1683 email = get_first_from_addr(mime);
1684 if (email != NULL)
1685 snprintf(default_key, sizeof(default_key),
1686 "--default-key %s", email);
1687
1688 /* part to encrypt */
1689
1690 /* encode quoted printable all text parts */
1691
1692 mailprivacy_prepare_mime(mime);
1693
1694 original_f = mailprivacy_get_tmp_file(privacy, original_filename,
1695 sizeof(original_filename));
1696 if (original_f == NULL) {
1697 res = MAIL_ERROR_FILE;
1698 goto err;
1699 }
1700
1701 col = 0;
1702 r = mailmime_write(original_f, &col, mime);
1703 if (r != MAILIMF_NO_ERROR) {
1704 fclose(original_f);
1705 res = MAIL_ERROR_FILE;
1706 goto unlink_original;
1707 }
1708
1709 fclose(original_f);
1710
1711 /* prepare destination file for encryption */
1712
1713 encrypted_f = mailprivacy_get_tmp_file(privacy,
1714 encrypted_filename,
1715 sizeof(encrypted_filename));
1716 if (encrypted_f == NULL) {
1717 res = MAIL_ERROR_FILE;
1718 goto unlink_original;
1719 }
1720 fclose(encrypted_f);
1721
1722 r = mail_quote_filename(quoted_original_filename,
1723 sizeof(quoted_original_filename), original_filename);
1724 if (r < 0) {
1725 res = MAIL_ERROR_MEMORY;
1726 goto unlink_encrypted;
1727 }
1728
1729 r = mail_quote_filename(quoted_encrypted_filename,
1730 sizeof(quoted_encrypted_filename), encrypted_filename);
1731 if (r < 0) {
1732 res = MAIL_ERROR_MEMORY;
1733 goto unlink_encrypted;
1734 }
1735
1736 snprintf(command, sizeof(command),
1737 "gpg -q %s -a --batch --yes --digest-algo sha1 --out %s -s %s -e %s 2>/dev/null",
1738 recipient, quoted_encrypted_filename, default_key,
1739 quoted_original_filename);
1740
1741 r = system(command);
1742 if (WEXITSTATUS(r) != 0) {
1743 res = MAIL_ERROR_COMMAND;
1744 goto unlink_encrypted;
1745 }
1746
1747 /* multipart */
1748
1749 multipart = mailprivacy_new_file_part(privacy, NULL,
1750 "multipart/encrypted", -1);
1751
1752 content = multipart->mm_content_type;
1753
1754 param = mailmime_param_new_with_data("protocol",
1755 "application/pgp-encrypted");
1756 if (param == NULL) {
1757 mailmime_free(multipart);
1758 res = MAIL_ERROR_MEMORY;
1759 goto unlink_encrypted;
1760 }
1761
1762 r = clist_append(content->ct_parameters, param);
1763 if (r < 0) {
1764 mailmime_parameter_free(param);
1765 mailmime_free(multipart);
1766 res = MAIL_ERROR_MEMORY;
1767 goto unlink_encrypted;
1768 }
1769
1770 /* version part */
1771
1772 version_f = mailprivacy_get_tmp_file(privacy,
1773 version_filename,
1774 sizeof(version_filename));
1775 if (version_f == NULL) {
1776 mailprivacy_mime_clear(multipart);
1777 mailmime_free(multipart);
1778 res = MAIL_ERROR_FILE;
1779 goto unlink_encrypted;
1780 }
1781 written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f);
1782 if (written != sizeof(PGP_VERSION) - 1) {
1783 fclose(version_f);
1784 mailprivacy_mime_clear(multipart);
1785 mailmime_free(multipart);
1786 res = MAIL_ERROR_FILE;
1787 goto unlink_encrypted;
1788 }
1789 fclose(version_f);
1790
1791 version_mime = mailprivacy_new_file_part(privacy,
1792 version_filename,
1793 "application/pgp-encrypted",
1794 MAILMIME_MECHANISM_8BIT);
1795 if (r != MAIL_NO_ERROR) {
1796 mailprivacy_mime_clear(multipart);
1797 mailmime_free(multipart);
1798 res = r;
1799 goto unlink_version;
1800 }
1801
1802 r = mailmime_smart_add_part(multipart, version_mime);
1803 if (r != MAIL_NO_ERROR) {
1804 mailprivacy_mime_clear(version_mime);
1805 mailmime_free(version_mime);
1806 mailprivacy_mime_clear(multipart);
1807 mailmime_free(multipart);
1808 res = MAIL_ERROR_MEMORY;
1809 goto unlink_version;
1810 }
1811
1812 /* encrypted part */
1813
1814 encrypted_mime = mailprivacy_new_file_part(privacy,
1815 encrypted_filename,
1816 "application/octet-stream",
1817 MAILMIME_MECHANISM_8BIT);
1818 if (r != MAIL_NO_ERROR) {
1819 mailprivacy_mime_clear(multipart);
1820 mailmime_free(multipart);
1821 res = r;
1822 goto unlink_version;
1823 }
1824
1825 r = mailmime_smart_add_part(multipart, encrypted_mime);
1826 if (r != MAIL_NO_ERROR) {
1827 mailprivacy_mime_clear(encrypted_mime);
1828 mailmime_free(encrypted_mime);
1829 mailprivacy_mime_clear(multipart);
1830 mailmime_free(multipart);
1831 res = MAIL_ERROR_MEMORY;
1832 goto unlink_version;
1833 }
1834
1835 unlink(version_filename);
1836 unlink(encrypted_filename);
1837 unlink(original_filename);
1838
1839 * result = multipart;
1840
1841 return MAIL_NO_ERROR;
1842
1843 unlink_version:
1844 unlink(version_filename);
1845 unlink_encrypted:
1846 unlink(encrypted_filename);
1847 unlink_original:
1848 unlink(original_filename);
1849 err:
1850 return res;
1851}
1852
1853
1854static int pgp_encrypt_mime(struct mailprivacy * privacy,
1855 struct mailmime * mime, struct mailmime ** result)
1856{
1857 char original_filename[PATH_MAX];
1858 FILE * original_f;
1859 int res;
1860 int r;
1861 int col;
1862 char encrypted_filename[PATH_MAX];
1863 FILE * encrypted_f;
1864 char version_filename[PATH_MAX];
1865 FILE * version_f;
1866 char command[PATH_MAX];
1867 char quoted_original_filename[PATH_MAX];
1868 char quoted_encrypted_filename[PATH_MAX];
1869 struct mailmime * version_mime;
1870 struct mailmime * multipart;
1871 struct mailmime_content * content;
1872 struct mailmime_parameter * param;
1873 struct mailmime * encrypted_mime;
1874 char recipient[PATH_MAX];
1875 struct mailimf_fields * fields;
1876 struct mailmime * root;
1877 size_t written;
1878
1879 root = mime;
1880 while (root->mm_parent != NULL)
1881 root = root->mm_parent;
1882
1883 fields = NULL;
1884 if (root->mm_type == MAILMIME_MESSAGE)
1885 fields = root->mm_data.mm_message.mm_fields;
1886
1887 /* recipient */
1888
1889 collect_recipient(recipient, sizeof(recipient), fields);
1890
1891 /* part to encrypt */
1892
1893 /* encode quoted printable all text parts */
1894
1895 mailprivacy_prepare_mime(mime);
1896
1897 original_f = mailprivacy_get_tmp_file(privacy,
1898 original_filename, sizeof(original_filename));
1899 if (original_f == NULL) {
1900 res = MAIL_ERROR_FILE;
1901 goto err;
1902 }
1903
1904 col = 0;
1905 r = mailmime_write(original_f, &col, mime);
1906 if (r != MAILIMF_NO_ERROR) {
1907 fclose(original_f);
1908 res = MAIL_ERROR_FILE;
1909 goto unlink_original;
1910 }
1911
1912 fclose(original_f);
1913
1914 /* prepare destination file for encryption */
1915
1916 encrypted_f = mailprivacy_get_tmp_file(privacy,
1917 encrypted_filename,
1918 sizeof(encrypted_filename));
1919 if (encrypted_f == NULL) {
1920 res = MAIL_ERROR_FILE;
1921 goto unlink_original;
1922 }
1923 fclose(encrypted_f);
1924
1925 r = mail_quote_filename(quoted_original_filename,
1926 sizeof(quoted_original_filename), original_filename);
1927 if (r < 0) {
1928 res = MAIL_ERROR_MEMORY;
1929 goto unlink_encrypted;
1930 }
1931
1932 r = mail_quote_filename(quoted_encrypted_filename,
1933 sizeof(quoted_encrypted_filename), encrypted_filename);
1934 if (r < 0) {
1935 res = MAIL_ERROR_MEMORY;
1936 goto unlink_encrypted;
1937 }
1938
1939 snprintf(command, sizeof(command),
1940 "gpg -q %s -a --batch --yes --out %s -e %s 2>/dev/null",
1941 recipient, quoted_encrypted_filename, quoted_original_filename);
1942
1943 r = system(command);
1944 if (WEXITSTATUS(r) != 0) {
1945 res = MAIL_ERROR_COMMAND;
1946 goto unlink_encrypted;
1947 }
1948
1949 /* multipart */
1950
1951 multipart = mailprivacy_new_file_part(privacy, NULL,
1952 "multipart/encrypted", -1);
1953
1954 content = multipart->mm_content_type;
1955
1956 param = mailmime_param_new_with_data("protocol",
1957 "application/pgp-encrypted");
1958 if (param == NULL) {
1959 mailmime_free(multipart);
1960 res = MAIL_ERROR_MEMORY;
1961 goto unlink_encrypted;
1962 }
1963
1964 r = clist_append(content->ct_parameters, param);
1965 if (r < 0) {
1966 mailmime_parameter_free(param);
1967 mailmime_free(multipart);
1968 res = MAIL_ERROR_MEMORY;
1969 goto unlink_encrypted;
1970 }
1971
1972 /* version part */
1973
1974 version_f = mailprivacy_get_tmp_file(privacy,
1975 version_filename, sizeof(version_filename));
1976 if (version_f == NULL) {
1977 mailprivacy_mime_clear(multipart);
1978 mailmime_free(multipart);
1979 res = MAIL_ERROR_FILE;
1980 goto unlink_encrypted;
1981 }
1982 written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f);
1983 if (written != sizeof(PGP_VERSION) - 1) {
1984 fclose(version_f);
1985 mailprivacy_mime_clear(multipart);
1986 mailmime_free(multipart);
1987 res = MAIL_ERROR_FILE;
1988 goto unlink_encrypted;
1989 }
1990 fclose(version_f);
1991
1992 version_mime = mailprivacy_new_file_part(privacy,
1993 version_filename,
1994 "application/pgp-encrypted",
1995 MAILMIME_MECHANISM_8BIT);
1996 if (r != MAIL_NO_ERROR) {
1997 mailprivacy_mime_clear(multipart);
1998 mailmime_free(multipart);
1999 res = r;
2000 goto unlink_version;
2001 }
2002
2003 r = mailmime_smart_add_part(multipart, version_mime);
2004 if (r != MAIL_NO_ERROR) {
2005 mailprivacy_mime_clear(version_mime);
2006 mailmime_free(version_mime);
2007 mailprivacy_mime_clear(multipart);
2008 mailmime_free(multipart);
2009 res = MAIL_ERROR_MEMORY;
2010 goto unlink_version;
2011 }
2012
2013 /* encrypted part */
2014
2015 encrypted_mime = mailprivacy_new_file_part(privacy,
2016 encrypted_filename,
2017 "application/octet-stream",
2018 MAILMIME_MECHANISM_8BIT);
2019 if (r != MAIL_NO_ERROR) {
2020 mailprivacy_mime_clear(multipart);
2021 mailmime_free(multipart);
2022 res = r;
2023 goto unlink_version;
2024 }
2025
2026 r = mailmime_smart_add_part(multipart, encrypted_mime);
2027 if (r != MAIL_NO_ERROR) {
2028 mailprivacy_mime_clear(encrypted_mime);
2029 mailmime_free(encrypted_mime);
2030 mailprivacy_mime_clear(multipart);
2031 mailmime_free(multipart);
2032 res = MAIL_ERROR_MEMORY;
2033 goto unlink_version;
2034 }
2035
2036 unlink(version_filename);
2037 unlink(encrypted_filename);
2038 unlink(original_filename);
2039
2040 * result = multipart;
2041
2042 return MAIL_NO_ERROR;
2043
2044 unlink_version:
2045 unlink(version_filename);
2046 unlink_encrypted:
2047 unlink(encrypted_filename);
2048 unlink_original:
2049 unlink(original_filename);
2050 err:
2051 return res;
2052}
2053
2054static int pgp_clear_sign(struct mailprivacy * privacy,
2055 struct mailmime * mime, struct mailmime ** result)
2056{
2057 char default_key[PATH_MAX];
2058 char original_filename[PATH_MAX];
2059 FILE * original_f;
2060 char signed_filename[PATH_MAX];
2061 FILE * signed_f;
2062 char quoted_original_filename[PATH_MAX];
2063 char quoted_signed_filename[PATH_MAX];
2064 int col;
2065 struct mailmime * signed_mime;
2066 int res;
2067 int r;
2068 char command[PATH_MAX];
2069 struct mailmime_content * content_type;
2070 char * email;
2071
2072 if (mime->mm_type != MAILMIME_SINGLE) {
2073 res = MAIL_ERROR_INVAL;
2074 goto err;
2075 }
2076
2077 if (mime->mm_data.mm_single == NULL) {
2078 res = MAIL_ERROR_INVAL;
2079 goto err;
2080 }
2081
2082 /* get signing key */
2083
2084 * default_key = '\0';
2085 email = get_first_from_addr(mime);
2086 if (email != NULL)
2087 snprintf(default_key, sizeof(default_key),
2088 "--default-key %s", email);
2089
2090 /* get part to sign */
2091
2092 original_f = mailprivacy_get_tmp_file(privacy,
2093 original_filename,
2094 sizeof(original_filename));
2095 if (original_f == NULL) {
2096 res = MAIL_ERROR_FILE;
2097 goto err;
2098 }
2099
2100 col = 0;
2101 r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1);
2102 if (r != MAILIMF_NO_ERROR) {
2103 fclose(original_f);
2104 res = MAIL_ERROR_FILE;
2105 goto unlink_original;
2106 }
2107 fclose(original_f);
2108
2109 signed_f = mailprivacy_get_tmp_file(privacy,
2110 signed_filename,
2111 sizeof(signed_filename));
2112 if (signed_f == NULL) {
2113 res = MAIL_ERROR_FILE;
2114 goto unlink_original;
2115 }
2116 fclose(signed_f);
2117
2118 r = mail_quote_filename(quoted_original_filename,
2119 sizeof(quoted_original_filename), original_filename);
2120 if (r < 0) {
2121 res = MAIL_ERROR_MEMORY;
2122 goto unlink_signed;
2123 }
2124
2125 r = mail_quote_filename(quoted_signed_filename,
2126 sizeof(quoted_signed_filename), signed_filename);
2127 if (r < 0) {
2128 res = MAIL_ERROR_MEMORY;
2129 goto unlink_signed;
2130 }
2131
2132 snprintf(command, sizeof(command),
2133 "gpg -q --batch --yes --digest-algo sha1 --out %s %s --clearsign %s 2>/dev/null",
2134 quoted_signed_filename, default_key, quoted_original_filename);
2135
2136 r = system(command);
2137 if (WEXITSTATUS(r) != 0) {
2138 res = MAIL_ERROR_COMMAND;
2139 goto unlink_signed;
2140 }
2141
2142 /* building the signed part */
2143
2144 signed_mime = mailprivacy_new_file_part(privacy, signed_filename,
2145 NULL, MAILMIME_MECHANISM_8BIT);
2146 if (signed_mime == NULL) {
2147 res = MAIL_ERROR_MEMORY;
2148 goto unlink_signed;
2149 }
2150
2151 /* place original content type */
2152
2153 content_type = mailmime_content_dup(mime->mm_content_type);
2154 if (content_type == NULL) {
2155 mailprivacy_mime_clear(signed_mime);
2156 mailmime_free(signed_mime);
2157 res = MAIL_ERROR_MEMORY;
2158 goto unlink_signed;
2159 }
2160
2161 mailmime_content_free(signed_mime->mm_content_type);
2162 signed_mime->mm_content_type = content_type;
2163
2164 /* place original MIME fields */
2165
2166 if (mime->mm_mime_fields != NULL) {
2167 struct mailmime_fields * mime_fields;
2168 clistiter * cur;
2169
2170 mime_fields = mailprivacy_mime_fields_dup(privacy,
2171 mime->mm_mime_fields);
2172 if (mime_fields == NULL) {
2173 mailprivacy_mime_clear(signed_mime);
2174 mailmime_free(signed_mime);
2175 res = MAIL_ERROR_MEMORY;
2176 goto unlink_signed;
2177 }
2178 for(cur = clist_begin(mime_fields->fld_list) ;
2179 cur != NULL ; cur = clist_next(cur)) {
2180 struct mailmime_field * field;
2181
2182 field = clist_content(cur);
2183 if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) {
2184 mailmime_field_free(field);
2185 clist_delete(mime_fields->fld_list, cur);
2186 break;
2187 }
2188 }
2189 clist_concat(signed_mime->mm_mime_fields->fld_list,
2190 mime_fields->fld_list);
2191 mailmime_fields_free(mime_fields);
2192 }
2193
2194 unlink(signed_filename);
2195 unlink(original_filename);
2196
2197 * result = signed_mime;
2198
2199 return MAIL_NO_ERROR;
2200
2201 unlink_signed:
2202 unlink(signed_filename);
2203 unlink_original:
2204 unlink(original_filename);
2205 err:
2206 return res;
2207}
2208
2209
2210static int pgp_armor_encrypt(struct mailprivacy * privacy,
2211 struct mailmime * mime, struct mailmime ** result)
2212{
2213 char original_filename[PATH_MAX];
2214 FILE * original_f;
2215 char encrypted_filename[PATH_MAX];
2216 FILE * encrypted_f;
2217 char quoted_original_filename[PATH_MAX];
2218 char quoted_encrypted_filename[PATH_MAX];
2219 int col;
2220 struct mailmime * encrypted_mime;
2221 int res;
2222 int r;
2223 char command[PATH_MAX];
2224 struct mailmime_content * content_type;
2225 struct mailmime * root;
2226 struct mailimf_fields * fields;
2227 char recipient[PATH_MAX];
2228
2229 if (mime->mm_type != MAILMIME_SINGLE) {
2230 res = MAIL_ERROR_INVAL;
2231 goto err;
2232 }
2233
2234 if (mime->mm_data.mm_single == NULL) {
2235 res = MAIL_ERROR_INVAL;
2236 goto err;
2237 }
2238
2239 root = mime;
2240 while (root->mm_parent != NULL)
2241 root = root->mm_parent;
2242
2243 fields = NULL;
2244 if (root->mm_type == MAILMIME_MESSAGE)
2245 fields = root->mm_data.mm_message.mm_fields;
2246
2247 /* recipient */
2248
2249 collect_recipient(recipient, sizeof(recipient), fields);
2250
2251 /* get part to encrypt */
2252
2253 original_f = mailprivacy_get_tmp_file(privacy, original_filename,
2254 sizeof(original_filename));
2255 if (original_f == NULL) {
2256 res = MAIL_ERROR_FILE;
2257 goto err;
2258 }
2259
2260 col = 0;
2261 r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1);
2262 if (r != MAILIMF_NO_ERROR) {
2263 fclose(original_f);
2264 res = MAIL_ERROR_FILE;
2265 goto unlink_original;
2266 }
2267 fclose(original_f);
2268
2269 encrypted_f = mailprivacy_get_tmp_file(privacy,
2270 encrypted_filename,
2271 sizeof(encrypted_filename));
2272 if (encrypted_f == NULL) {
2273 res = MAIL_ERROR_FILE;
2274 goto unlink_original;
2275 }
2276 fclose(encrypted_f);
2277
2278 r = mail_quote_filename(quoted_original_filename,
2279 sizeof(quoted_original_filename), original_filename);
2280 if (r < 0) {
2281 res = MAIL_ERROR_MEMORY;
2282 goto unlink_encrypted;
2283 }
2284
2285 r = mail_quote_filename(quoted_encrypted_filename,
2286 sizeof(quoted_encrypted_filename), encrypted_filename);
2287 if (r < 0) {
2288 res = MAIL_ERROR_MEMORY;
2289 goto unlink_encrypted;
2290 }
2291
2292 snprintf(command, sizeof(command),
2293 "gpg -q %s --batch --yes --out %s -e --armor %s 2>/dev/null",
2294 recipient, quoted_encrypted_filename, quoted_original_filename);
2295
2296 r = system(command);
2297 if (WEXITSTATUS(r) != 0) {
2298 res = MAIL_ERROR_COMMAND;
2299 goto unlink_encrypted;
2300 }
2301
2302 /* building the encrypted part */
2303
2304 encrypted_mime = mailprivacy_new_file_part(privacy,
2305 encrypted_filename,
2306 "application/octet-stream",
2307 MAILMIME_MECHANISM_8BIT);
2308 if (encrypted_mime == NULL) {
2309 res = MAIL_ERROR_MEMORY;
2310 goto unlink_encrypted;
2311 }
2312
2313 /* place original content type */
2314
2315 content_type = mailmime_content_dup(mime->mm_content_type);
2316 if (content_type == NULL) {
2317 mailprivacy_mime_clear(encrypted_mime);
2318 mailmime_free(encrypted_mime);
2319 res = MAIL_ERROR_MEMORY;
2320 goto unlink_encrypted;
2321 }
2322
2323 mailmime_content_free(encrypted_mime->mm_content_type);
2324 encrypted_mime->mm_content_type = content_type;
2325
2326 /* place original MIME fields */
2327
2328 if (mime->mm_mime_fields != NULL) {
2329 struct mailmime_fields * mime_fields;
2330 clistiter * cur;
2331
2332 mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields);
2333 if (mime_fields == NULL) {
2334 mailprivacy_mime_clear(encrypted_mime);
2335 mailmime_free(encrypted_mime);
2336 res = MAIL_ERROR_MEMORY;
2337 goto unlink_encrypted;
2338 }
2339 for(cur = clist_begin(mime_fields->fld_list) ;
2340 cur != NULL ; cur = clist_next(cur)) {
2341 struct mailmime_field * field;
2342
2343 field = clist_content(cur);
2344 if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) {
2345 mailmime_field_free(field);
2346 clist_delete(mime_fields->fld_list, cur);
2347 break;
2348 }
2349 }
2350 clist_concat(encrypted_mime->mm_mime_fields->fld_list,
2351 mime_fields->fld_list);
2352 mailmime_fields_free(mime_fields);
2353 }
2354
2355 unlink(encrypted_filename);
2356 unlink(original_filename);
2357
2358 * result = encrypted_mime;
2359
2360 return MAIL_NO_ERROR;
2361
2362 unlink_encrypted:
2363 unlink(encrypted_filename);
2364 unlink_original:
2365 unlink(original_filename);
2366 err:
2367 return res;
2368}
2369
2370
2371static int pgp_armor_sign_encrypt(struct mailprivacy * privacy,
2372 struct mailmime * mime, struct mailmime ** result)
2373{
2374 char default_key[PATH_MAX];
2375 char original_filename[PATH_MAX];
2376 FILE * original_f;
2377 char encrypted_filename[PATH_MAX];
2378 FILE * encrypted_f;
2379 char quoted_original_filename[PATH_MAX];
2380 char quoted_encrypted_filename[PATH_MAX];
2381 int col;
2382 struct mailmime * encrypted_mime;
2383 int res;
2384 int r;
2385 char command[PATH_MAX];
2386 struct mailmime_content * content_type;
2387 struct mailmime * root;
2388 struct mailimf_fields * fields;
2389 char recipient[PATH_MAX];
2390 char * email;
2391
2392 if (mime->mm_type != MAILMIME_SINGLE) {
2393 res = MAIL_ERROR_INVAL;
2394 goto err;
2395 }
2396
2397 if (mime->mm_data.mm_single == NULL) {
2398 res = MAIL_ERROR_INVAL;
2399 goto err;
2400 }
2401
2402 /* get signing key */
2403
2404 * default_key = '\0';
2405 email = get_first_from_addr(mime);
2406 if (email != NULL)
2407 snprintf(default_key, sizeof(default_key),
2408 "--default-key %s", email);
2409
2410 root = mime;
2411 while (root->mm_parent != NULL)
2412 root = root->mm_parent;
2413
2414 fields = NULL;
2415 if (root->mm_type == MAILMIME_MESSAGE)
2416 fields = root->mm_data.mm_message.mm_fields;
2417
2418 /* recipient */
2419
2420 collect_recipient(recipient, sizeof(recipient), fields);
2421
2422 /* get part to encrypt */
2423
2424 original_f = mailprivacy_get_tmp_file(privacy,
2425 original_filename,
2426 sizeof(original_filename));
2427 if (original_f == NULL) {
2428 res = MAIL_ERROR_FILE;
2429 goto err;
2430 }
2431
2432 col = 0;
2433 r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1);
2434 if (r != MAILIMF_NO_ERROR) {
2435 fclose(original_f);
2436 res = MAIL_ERROR_FILE;
2437 goto unlink_original;
2438 }
2439 fclose(original_f);
2440
2441 encrypted_f = mailprivacy_get_tmp_file(privacy,
2442 encrypted_filename,
2443 sizeof(encrypted_filename));
2444 if (encrypted_f == NULL) {
2445 res = MAIL_ERROR_FILE;
2446 goto unlink_original;
2447 }
2448 fclose(encrypted_f);
2449
2450 r = mail_quote_filename(quoted_original_filename,
2451 sizeof(quoted_original_filename), original_filename);
2452 if (r < 0) {
2453 res = MAIL_ERROR_MEMORY;
2454 goto unlink_encrypted;
2455 }
2456
2457 r = mail_quote_filename(quoted_encrypted_filename,
2458 sizeof(quoted_encrypted_filename), encrypted_filename);
2459 if (r < 0) {
2460 res = MAIL_ERROR_MEMORY;
2461 goto unlink_encrypted;
2462 }
2463
2464 snprintf(command, sizeof(command),
2465 "gpg -q %s --batch --yes --digest-algo sha1 "
2466 "--out %s %s -e -s -a %s 2>/dev/null",
2467 recipient, encrypted_filename, default_key, original_filename);
2468
2469 r = system(command);
2470 if (WEXITSTATUS(r) != 0) {
2471 res = MAIL_ERROR_COMMAND;
2472 goto unlink_encrypted;
2473 }
2474
2475 /* building the encrypted part */
2476
2477 encrypted_mime = mailprivacy_new_file_part(privacy,
2478 encrypted_filename,
2479 "application/octet-stream",
2480 MAILMIME_MECHANISM_8BIT);
2481 if (encrypted_mime == NULL) {
2482 res = MAIL_ERROR_MEMORY;
2483 goto unlink_encrypted;
2484 }
2485
2486 /* place original content type */
2487
2488 content_type = mailmime_content_dup(mime->mm_content_type);
2489 if (content_type == NULL) {
2490 mailprivacy_mime_clear(encrypted_mime);
2491 mailmime_free(encrypted_mime);
2492 res = MAIL_ERROR_MEMORY;
2493 goto unlink_encrypted;
2494 }
2495
2496 mailmime_content_free(encrypted_mime->mm_content_type);
2497 encrypted_mime->mm_content_type = content_type;
2498
2499 /* place original MIME fields */
2500
2501 if (mime->mm_mime_fields != NULL) {
2502 struct mailmime_fields * mime_fields;
2503 clistiter * cur;
2504
2505 mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields);
2506 if (mime_fields == NULL) {
2507 mailprivacy_mime_clear(encrypted_mime);
2508 mailmime_free(encrypted_mime);
2509 res = MAIL_ERROR_MEMORY;
2510 goto unlink_encrypted;
2511 }
2512 for(cur = clist_begin(mime_fields->fld_list) ;
2513 cur != NULL ; cur = clist_next(cur)) {
2514 struct mailmime_field * field;
2515
2516 field = clist_content(cur);
2517 if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) {
2518 mailmime_field_free(field);
2519 clist_delete(mime_fields->fld_list, cur);
2520 break;
2521 }
2522 }
2523 clist_concat(encrypted_mime->mm_mime_fields->fld_list,
2524 mime_fields->fld_list);
2525 mailmime_fields_free(mime_fields);
2526 }
2527
2528 unlink(encrypted_filename);
2529 unlink(original_filename);
2530
2531 * result = encrypted_mime;
2532
2533 return MAIL_NO_ERROR;
2534
2535 unlink_encrypted:
2536 unlink(encrypted_filename);
2537 unlink_original:
2538 unlink(original_filename);
2539 err:
2540 return res;
2541}
2542
2543
2544static struct mailprivacy_encryption pgp_encryption_tab[] = {
2545 /* PGP signed part */
2546 {
2547 .name = "signed",
2548 .description = "PGP signed part",
2549 .encrypt = pgp_sign_mime,
2550 },
2551
2552 /* PGP encrypted part */
2553
2554 {
2555 .name = "encrypted",
2556 .description = "PGP encrypted part",
2557 .encrypt = pgp_encrypt_mime,
2558 },
2559
2560 /* PGP signed & encrypted part */
2561
2562 {
2563 .name = "signed-encrypted",
2564 .description = "PGP signed & encrypted part",
2565 .encrypt = pgp_sign_encrypt_mime,
2566 },
2567
2568 /* PGP clear signed part */
2569
2570 {
2571 .name = "clear-signed",
2572 .description = "PGP clear signed part",
2573 .encrypt = pgp_clear_sign,
2574 },
2575
2576 /* PGP armor encrypted part */
2577
2578 {
2579 .name = "encrypted-armor",
2580 .description = "PGP ASCII armor encrypted part",
2581 .encrypt = pgp_armor_encrypt,
2582 },
2583
2584 /* PGP armor signed & encrypted part */
2585
2586 {
2587 .name = "signed-encrypted-armor",
2588 .description = "PGP ASCII armor signed & encrypted part",
2589 .encrypt = pgp_armor_sign_encrypt,
2590 },
2591};
2592
2593static struct mailprivacy_protocol pgp_protocol = {
2594 .name = "pgp",
2595 .description = "OpenPGP",
2596
2597 .is_encrypted = pgp_test_encrypted,
2598 .decrypt = pgp_handler,
2599
2600 .encryption_count =
2601 (sizeof(pgp_encryption_tab) / sizeof(pgp_encryption_tab[0])),
2602
2603 .encryption_tab = pgp_encryption_tab,
2604};
2605
2606int mailprivacy_gnupg_init(struct mailprivacy * privacy)
2607{
2608 return mailprivacy_register(privacy, &pgp_protocol);
2609}
2610
2611void mailprivacy_gnupg_done(struct mailprivacy * privacy)
2612{
2613 mailprivacy_unregister(privacy, &pgp_protocol);
2614}
diff --git a/libetpan/src/engine/mailprivacy_gnupg.h b/libetpan/src/engine/mailprivacy_gnupg.h
new file mode 100644
index 0000000..013c8a4
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_gnupg.h
@@ -0,0 +1,46 @@
1/*
2 * etPan! -- a mail user agent
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_GNUPG_H
37
38#define MAIL_PRIVACY_GNUPG_H
39
40#include <libetpan/mailprivacy_types.h>
41
42int mailprivacy_gnupg_init(struct mailprivacy * privacy);
43
44void mailprivacy_gnupg_done(struct mailprivacy * privacy);
45
46#endif
diff --git a/libetpan/src/engine/mailprivacy_smime.c b/libetpan/src/engine/mailprivacy_smime.c
new file mode 100644
index 0000000..43eb69f
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_smime.c
@@ -0,0 +1,1755 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailprivacy_smime.h"
37#include <string.h>
38#include <sys/wait.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include "mailprivacy_tools.h"
45#include "mailprivacy.h"
46#include <stdlib.h>
47#include <dirent.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <libetpan/libetpan-config.h>
51
52/*
53 global variable
54
55 TODO : instance of privacy drivers
56*/
57
58static char cert_dir[PATH_MAX] = "";
59static chash * certificates = NULL;
60static chash * private_keys = NULL;
61static char CAcert_dir[PATH_MAX] = "";
62static char * CAfile = NULL;
63static int CA_check = 1;
64static int store_cert = 0;
65static char private_keys_dir[PATH_MAX] = "";
66
67static char * get_cert_file(char * email);
68
69static char * get_private_key_file(char * email);
70
71
72static int smime_is_signed(struct mailmime * mime)
73{
74 if (mime->mm_content_type != NULL) {
75 clistiter * cur;
76
77 for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; cur != NULL ;
78 cur = clist_next(cur)) {
79 struct mailmime_parameter * param;
80
81 param = cur->data;
82
83 if ((strcasecmp(param->pa_name, "protocol") == 0) &&
84 ((strcasecmp(param->pa_value, "application/x-pkcs7-signature") == 0) ||
85 (strcasecmp(param->pa_value, "application/pkcs7-signature") == 0)))
86 return 1;
87 }
88 }
89
90 return 0;
91}
92
93static int smime_is_encrypted(struct mailmime * mime)
94{
95 if (mime->mm_content_type != NULL) {
96 if ((strcasecmp(mime->mm_content_type->ct_subtype, "x-pkcs7-mime") == 0) ||
97 (strcasecmp(mime->mm_content_type->ct_subtype, "pkcs7-mime") == 0))
98 return 1;
99 }
100
101 return 0;
102}
103
104#define BUF_SIZE 1024
105
106enum {
107 NO_ERROR_SMIME = 0,
108 ERROR_SMIME_CHECK,
109 ERROR_SMIME_COMMAND,
110 ERROR_SMIME_FILE,
111};
112
113/* write output to a file */
114
115static int get_smime_output(FILE * dest_f, char * command)
116{
117 FILE * p;
118 char buf[BUF_SIZE];
119 size_t size;
120 int res;
121 int status;
122 char command_redirected[PATH_MAX];
123
124 snprintf(command_redirected, sizeof(command_redirected), "%s 2>&1", command);
125
126 /*
127 flush buffer so that it is not flushed more than once when forking
128 */
129 fflush(dest_f);
130
131 p = popen(command_redirected, "r");
132 if (p == NULL) {
133 res = ERROR_SMIME_COMMAND;
134 goto err;
135 }
136
137 while ((size = fread(buf, 1, sizeof(buf), p)) != 0) {
138 size_t written;
139
140 written = fwrite(buf, 1, size, dest_f);
141 if (written != size) {
142 res = ERROR_SMIME_FILE;
143 goto close;
144 }
145 }
146 status = pclose(p);
147
148 if (WEXITSTATUS(status) != 0)
149 return ERROR_SMIME_CHECK;
150 else
151 return NO_ERROR_SMIME;
152
153 close:
154 pclose(p);
155 err:
156 return res;
157}
158
159static char * get_first_from_addr(struct mailmime * mime)
160{
161 clistiter * cur;
162 struct mailimf_single_fields single_fields;
163 struct mailimf_fields * fields;
164 struct mailimf_mailbox * mb;
165
166 while (mime->mm_parent != NULL)
167 mime = mime->mm_parent;
168
169 if (mime->mm_type != MAILMIME_MESSAGE)
170 return NULL;
171
172 fields = mime->mm_data.mm_message.mm_fields;
173 if (fields == NULL)
174 return NULL;
175
176 mailimf_single_fields_init(&single_fields, fields);
177
178 if (single_fields.fld_from == NULL)
179 return NULL;
180
181 cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list);
182 if (cur == NULL)
183 return NULL;
184
185 mb = clist_content(cur);
186
187 return mb->mb_addr_spec;
188}
189
190#define SMIME_DECRYPT_DESCRIPTION "S/MIME encrypted part\r\n"
191#define SMIME_DECRYPT_FAILED "S/MIME decryption FAILED\r\n"
192#define SMIME_DECRYPT_SUCCESS "S/MIME decryption success\r\n"
193
194static int smime_decrypt(struct mailprivacy * privacy,
195 mailmessage * msg,
196 struct mailmime * mime, struct mailmime ** result)
197{
198 char smime_filename[PATH_MAX];
199 char quoted_smime_filename[PATH_MAX];
200 char description_filename[PATH_MAX];
201 FILE * description_f;
202 char decrypted_filename[PATH_MAX];
203 FILE * decrypted_f;
204 char command[PATH_MAX];
205 struct mailmime * description_mime;
206 struct mailmime * decrypted_mime;
207 int r;
208 int res;
209 int sign_ok;
210 char quoted_decrypted_filename[PATH_MAX];
211 struct mailmime * multipart;
212 char * smime_cert;
213 char * smime_key;
214 char quoted_smime_cert[PATH_MAX];
215 char quoted_smime_key[PATH_MAX];
216 char * email;
217 chashiter * iter;
218
219 /* fetch the whole multipart and write it to a file */
220
221 r = mailprivacy_fetch_mime_body_to_file(privacy,
222 smime_filename, sizeof(smime_filename),
223 msg, mime);
224 if (r != MAIL_NO_ERROR) {
225 res = r;
226 goto err;
227 }
228
229 /* we are in a safe directory */
230
231 decrypted_f = mailprivacy_get_tmp_file(privacy,
232 decrypted_filename,
233 sizeof(decrypted_filename));
234 if (decrypted_f == NULL) {
235 res = MAIL_ERROR_FILE;
236 goto unlink_smime;
237 }
238 fclose(decrypted_f);
239
240 sign_ok = 0;
241 for(iter = chash_begin(private_keys) ; iter != NULL ;
242 iter = chash_next(private_keys, iter)) {
243 chashdatum key;
244 char email_buf[BUF_SIZE];
245
246 chash_key(iter, &key);
247
248 if (key.len >= sizeof(email_buf))
249 continue;
250
251 strncpy(email_buf, key.data, key.len);
252 email_buf[key.len] = '\0';
253 email = email_buf;
254
255 /* description */
256
257 description_f = mailprivacy_get_tmp_file(privacy,
258 description_filename,
259 sizeof(description_filename));
260 if (description_f == NULL) {
261 res = MAIL_ERROR_FILE;
262 goto unlink_decrypted;
263 }
264
265 fprintf(description_f, SMIME_DECRYPT_DESCRIPTION);
266
267 /* get encryption key */
268
269#if 0
270 email = get_first_from_addr(mime);
271 if (email == NULL) {
272 fclose(description_f);
273 res = MAIL_ERROR_INVAL;
274 goto unlink_description;
275 }
276#endif
277
278 smime_key = get_private_key_file(email);
279 smime_cert = get_cert_file(email);
280 if ((smime_cert == NULL) || (smime_key == NULL)) {
281 fclose(description_f);
282 res = MAIL_ERROR_INVAL;
283 goto unlink_description;
284 }
285
286 r = mail_quote_filename(quoted_smime_cert, sizeof(quoted_smime_cert),
287 smime_cert);
288 if (r < 0) {
289 fclose(description_f);
290 res = MAIL_ERROR_MEMORY;
291 goto unlink_description;
292 }
293
294 r = mail_quote_filename(quoted_smime_key, sizeof(quoted_smime_key),
295 smime_key);
296 if (r < 0) {
297 fclose(description_f);
298 res = MAIL_ERROR_MEMORY;
299 goto unlink_description;
300 }
301
302 /* run the command */
303
304 r = mail_quote_filename(quoted_smime_filename,
305 sizeof(quoted_smime_filename), smime_filename);
306 if (r < 0) {
307 fclose(description_f);
308 res = MAIL_ERROR_MEMORY;
309 goto unlink_description;
310 }
311
312 r = mail_quote_filename(quoted_decrypted_filename,
313 sizeof(quoted_decrypted_filename), decrypted_filename);
314 if (r < 0) {
315 fclose(description_f);
316 res = MAIL_ERROR_MEMORY;
317 goto unlink_description;
318 }
319
320 sign_ok = 0;
321 snprintf(command, PATH_MAX,
322 "openssl smime -decrypt -in %s -out %s -inkey %s -recip %s",
323 quoted_smime_filename, quoted_decrypted_filename,
324 quoted_smime_key, quoted_smime_cert);
325
326 r = get_smime_output(description_f, command);
327 switch (r) {
328 case NO_ERROR_SMIME:
329 sign_ok = 1;
330 break;
331 case ERROR_SMIME_CHECK:
332 sign_ok = 0;
333 break;
334 case ERROR_SMIME_COMMAND:
335 fclose(description_f);
336 res = MAIL_ERROR_COMMAND;
337 goto unlink_description;
338 case ERROR_SMIME_FILE:
339 fclose(description_f);
340 res = MAIL_ERROR_FILE;
341 goto unlink_description;
342 }
343
344 if (sign_ok) {
345 fprintf(description_f, SMIME_DECRYPT_SUCCESS);
346 fclose(description_f);
347 break;
348 }
349 else {
350 fclose(description_f);
351 unlink(description_filename);
352 }
353 }
354
355 if (!sign_ok) {
356 description_f = mailprivacy_get_tmp_file(privacy,
357 description_filename,
358 sizeof(description_filename));
359 if (description_f == NULL) {
360 res = MAIL_ERROR_FILE;
361 goto unlink_decrypted;
362 }
363
364 fprintf(description_f, SMIME_DECRYPT_DESCRIPTION);
365 fprintf(description_f, SMIME_DECRYPT_FAILED);
366 fclose(description_f);
367 }
368
369 /* building multipart */
370
371 r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart);
372 if (r != MAILIMF_NO_ERROR) {
373 res = MAIL_ERROR_MEMORY;
374 goto unlink_description;
375 }
376
377 /* building the description part */
378
379 description_mime = mailprivacy_new_file_part(privacy,
380 description_filename,
381 "text/plain", MAILMIME_MECHANISM_8BIT);
382 if (description_mime == NULL) {
383 mailprivacy_mime_clear(multipart);
384 mailmime_free(multipart);
385 res = MAIL_ERROR_MEMORY;
386 goto unlink_description;
387 }
388
389 /* adds the description part */
390
391 r = mailmime_smart_add_part(multipart, description_mime);
392 if (r != MAIL_NO_ERROR) {
393 mailprivacy_mime_clear(description_mime);
394 mailmime_free(description_mime);
395 mailprivacy_mime_clear(multipart);
396 mailmime_free(multipart);
397 res = MAIL_ERROR_MEMORY;
398 goto unlink_description;
399 }
400
401 /* building the decrypted part */
402
403 r = mailprivacy_get_part_from_file(privacy, 1,
404 decrypted_filename, &decrypted_mime);
405 if (r == MAIL_NO_ERROR) {
406 /* adds the decrypted part */
407
408 r = mailmime_smart_add_part(multipart, decrypted_mime);
409 if (r != MAIL_NO_ERROR) {
410 mailprivacy_mime_clear(decrypted_mime);
411 mailmime_free(decrypted_mime);
412 mailprivacy_mime_clear(multipart);
413 mailmime_free(multipart);
414 res = MAIL_ERROR_MEMORY;
415 goto unlink_description;
416 }
417 }
418
419 unlink(description_filename);
420 unlink(decrypted_filename);
421 unlink(smime_filename);
422
423 * result = multipart;
424
425 return MAIL_NO_ERROR;
426
427 unlink_description:
428 unlink(description_filename);
429 unlink_decrypted:
430 unlink(decrypted_filename);
431 unlink_smime:
432 unlink(smime_filename);
433 err:
434 return res;
435}
436
437
438static int get_cert_from_sig(struct mailprivacy * privacy,
439 mailmessage * msg,
440 struct mailmime * mime);
441
442#define SMIME_VERIFY_DESCRIPTION "S/MIME verify signed message\r\n"
443#define SMIME_VERIFY_FAILED "S/MIME verification FAILED\r\n"
444#define SMIME_VERIFY_SUCCESS "S/MIME verification success\r\n"
445
446static int
447smime_verify(struct mailprivacy * privacy,
448 mailmessage * msg,
449 struct mailmime * mime, struct mailmime ** result)
450{
451 char smime_filename[PATH_MAX];
452 char quoted_smime_filename[PATH_MAX];
453 int res;
454 int r;
455 char command[PATH_MAX];
456 int sign_ok;
457 struct mailmime * description_mime;
458 FILE * description_f;
459 char description_filename[PATH_MAX];
460 struct mailmime * multipart;
461 char stripped_filename[PATH_MAX];
462 struct mailmime * stripped_mime;
463 char quoted_stripped_filename[PATH_MAX];
464 FILE * stripped_f;
465 char check_CA[PATH_MAX];
466 char quoted_CAfile[PATH_MAX];
467 char noverify[PATH_MAX];
468
469 if (store_cert)
470 get_cert_from_sig(privacy, msg, mime);
471
472 * check_CA = '\0';
473 if (CAfile != NULL) {
474 r = mail_quote_filename(quoted_CAfile, sizeof(quoted_CAfile), CAfile);
475 if (r < 0) {
476 res = MAIL_ERROR_MEMORY;
477 goto err;
478 }
479
480 snprintf(check_CA, sizeof(check_CA), "-CAfile %s", quoted_CAfile);
481 }
482
483 * noverify = '\0';
484 if (!CA_check) {
485 snprintf(noverify, sizeof(noverify), "-noverify");
486 }
487
488 /* fetch the whole multipart and write it to a file */
489
490 r = mailprivacy_fetch_mime_body_to_file(privacy,
491 smime_filename, sizeof(smime_filename),
492 msg, mime);
493 if (r != MAIL_NO_ERROR) {
494 res = r;
495 goto err;
496 }
497
498 stripped_f = mailprivacy_get_tmp_file(privacy,
499 stripped_filename,
500 sizeof(stripped_filename));
501 if (stripped_f == NULL) {
502 res = MAIL_ERROR_FILE;
503 goto unlink_smime;
504 }
505 fclose(stripped_f);
506
507 /* description */
508
509 description_f = mailprivacy_get_tmp_file(privacy,
510 description_filename,
511 sizeof(description_filename));
512 if (description_f == NULL) {
513 res = MAIL_ERROR_FILE;
514 goto unlink_stripped;
515 }
516
517 fprintf(description_f, SMIME_VERIFY_DESCRIPTION);
518
519 /* run the command */
520
521 r = mail_quote_filename(quoted_smime_filename,
522 sizeof(quoted_smime_filename), smime_filename);
523 if (r < 0) {
524 fclose(description_f);
525 res = MAIL_ERROR_MEMORY;
526 goto unlink_description;
527 }
528
529 r = mail_quote_filename(quoted_stripped_filename,
530 sizeof(quoted_stripped_filename), stripped_filename);
531 if (r < 0) {
532 fclose(description_f);
533 res = MAIL_ERROR_MEMORY;
534 goto unlink_description;
535 }
536
537 sign_ok = 0;
538 snprintf(command, PATH_MAX, "openssl smime -verify -in %s -out %s %s %s",
539 quoted_smime_filename, quoted_stripped_filename, check_CA, noverify);
540
541 r = get_smime_output(description_f, command);
542 switch (r) {
543 case NO_ERROR_SMIME:
544 sign_ok = 1;
545 break;
546 case ERROR_SMIME_CHECK:
547 sign_ok = 0;
548 break;
549 case ERROR_SMIME_COMMAND:
550 fclose(description_f);
551 res = MAIL_ERROR_COMMAND;
552 goto unlink_description;
553 case ERROR_SMIME_FILE:
554 fclose(description_f);
555 res = MAIL_ERROR_FILE;
556 goto unlink_description;
557 }
558 if (sign_ok)
559 fprintf(description_f, SMIME_VERIFY_SUCCESS);
560 else
561 fprintf(description_f, SMIME_VERIFY_FAILED);
562 fclose(description_f);
563
564 /* building multipart */
565
566 r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart);
567 if (r != MAILIMF_NO_ERROR) {
568 res = MAIL_ERROR_MEMORY;
569 goto unlink_description;
570 }
571
572 /* building the description part */
573
574 description_mime = mailprivacy_new_file_part(privacy,
575 description_filename,
576 "text/plain", MAILMIME_MECHANISM_8BIT);
577 if (description_mime == NULL) {
578 mailprivacy_mime_clear(multipart);
579 mailmime_free(multipart);
580 res = MAIL_ERROR_MEMORY;
581 goto unlink_description;
582 }
583
584 /* adds the description part */
585
586 r = mailmime_smart_add_part(multipart, description_mime);
587 if (r != MAIL_NO_ERROR) {
588 mailprivacy_mime_clear(description_mime);
589 mailmime_free(description_mime);
590 mailprivacy_mime_clear(multipart);
591 mailmime_free(multipart);
592 res = MAIL_ERROR_MEMORY;
593 goto unlink_description;
594 }
595
596 r = mailprivacy_get_part_from_file(privacy, 1,
597 stripped_filename, &stripped_mime);
598 if (r != MAIL_NO_ERROR) {
599 mailprivacy_mime_clear(multipart);
600 mailmime_free(multipart);
601 res = r;
602 goto unlink_description;
603 }
604
605 r = mailmime_smart_add_part(multipart, stripped_mime);
606 if (r != MAIL_NO_ERROR) {
607 mailprivacy_mime_clear(stripped_mime);
608 mailmime_free(stripped_mime);
609 mailprivacy_mime_clear(multipart);
610 mailmime_free(multipart);
611 res = MAIL_ERROR_MEMORY;
612 goto unlink_description;
613 }
614
615 unlink(description_filename);
616 unlink(stripped_filename);
617 unlink(smime_filename);
618
619 * result = multipart;
620
621 return MAIL_NO_ERROR;
622
623 unlink_description:
624 unlink(description_filename);
625 unlink_stripped:
626 unlink(stripped_filename);
627 unlink_smime:
628 unlink(smime_filename);
629 err:
630 return res;
631}
632
633static int smime_test_encrypted(struct mailprivacy * privacy,
634 mailmessage * msg,
635 struct mailmime * mime)
636{
637 switch (mime->mm_type) {
638 case MAILMIME_MULTIPLE:
639 return smime_is_signed(mime);
640
641 case MAILMIME_SINGLE:
642 return smime_is_encrypted(mime);
643 }
644
645 return 0;
646}
647
648static int smime_handler(struct mailprivacy * privacy,
649 mailmessage * msg,
650 struct mailmime * mime, struct mailmime ** result)
651{
652 int r;
653 struct mailmime * alternative_mime;
654
655 alternative_mime = NULL;
656 switch (mime->mm_type) {
657 case MAILMIME_MULTIPLE:
658 r = MAIL_ERROR_INVAL;
659 if (smime_is_signed(mime))
660 r = smime_verify(privacy, msg, mime, &alternative_mime);
661
662 if (r != MAIL_NO_ERROR)
663 return r;
664
665 * result = alternative_mime;
666
667 return MAIL_NO_ERROR;
668
669 case MAILMIME_SINGLE:
670 r = MAIL_ERROR_INVAL;
671 if (smime_is_encrypted(mime))
672 r = smime_decrypt(privacy, msg, mime, &alternative_mime);
673
674 if (r != MAIL_NO_ERROR)
675 return r;
676
677 * result = alternative_mime;
678
679 return MAIL_NO_ERROR;
680 }
681
682 return MAIL_ERROR_INVAL;
683}
684
685
686
687
688static void strip_mime_headers(struct mailmime * mime)
689{
690 struct mailmime_fields * fields;
691 clistiter * cur;
692
693 fields = mime->mm_mime_fields;
694
695 if (fields == NULL)
696 return;
697
698 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
699 cur = clist_next(cur)) {
700 struct mailmime_field * field;
701
702 field = clist_content(cur);
703
704 if (field->fld_type == MAILMIME_FIELD_VERSION) {
705 mailmime_field_free(field);
706 clist_delete(fields->fld_list, cur);
707 break;
708 }
709 }
710}
711
712static int smime_sign(struct mailprivacy * privacy,
713 struct mailmime * mime, struct mailmime ** result)
714{
715 char signed_filename[PATH_MAX];
716 FILE * signed_f;
717 int res;
718 int r;
719 int col;
720 char signature_filename[PATH_MAX];
721 FILE * signature_f;
722 char command[PATH_MAX];
723 char quoted_signature_filename[PATH_MAX];
724 char quoted_signed_filename[PATH_MAX];
725 struct mailmime * signed_mime;
726 char * smime_cert;
727 char * smime_key;
728 char quoted_smime_cert[PATH_MAX];
729 char quoted_smime_key[PATH_MAX];
730 char * email;
731
732 /* get signing key */
733
734 email = get_first_from_addr(mime);
735 if (email == NULL) {
736 res = MAIL_ERROR_INVAL;
737 goto err;
738 }
739
740 smime_key = get_private_key_file(email);
741 smime_cert = get_cert_file(email);
742 if ((smime_cert == NULL) || (smime_key == NULL)) {
743 res = MAIL_ERROR_INVAL;
744 goto err;
745 }
746
747 /* part to sign */
748
749 /* encode quoted printable all text parts */
750
751 mailprivacy_prepare_mime(mime);
752
753 signed_f = mailprivacy_get_tmp_file(privacy,
754 signed_filename, sizeof(signed_filename));
755 if (signed_f == NULL) {
756 res = MAIL_ERROR_FILE;
757 goto err;
758 }
759
760 col = 0;
761 r = mailmime_write(signed_f, &col, mime);
762 if (r != MAILIMF_NO_ERROR) {
763 fclose(signed_f);
764 res = MAIL_ERROR_FILE;
765 goto unlink_signed;
766 }
767
768 fclose(signed_f);
769
770 /* prepare destination file for signature */
771
772 signature_f = mailprivacy_get_tmp_file(privacy,
773 signature_filename,
774 sizeof(signature_filename));
775 if (signature_f == NULL) {
776 res = MAIL_ERROR_FILE;
777 goto unlink_signed;
778 }
779 fclose(signature_f);
780
781 r = mail_quote_filename(quoted_signed_filename,
782 sizeof(quoted_signed_filename), signed_filename);
783 if (r < 0) {
784 res = MAIL_ERROR_MEMORY;
785 goto unlink_signature;
786 }
787
788 r = mail_quote_filename(quoted_signature_filename,
789 sizeof(quoted_signature_filename), signature_filename);
790 if (r < 0) {
791 res = MAIL_ERROR_MEMORY;
792 goto unlink_signature;
793 }
794
795 r = mail_quote_filename(quoted_smime_key,
796 sizeof(quoted_smime_key), smime_key);
797 if (r < 0) {
798 res = MAIL_ERROR_MEMORY;
799 goto unlink_signature;
800 }
801
802 r = mail_quote_filename(quoted_smime_cert,
803 sizeof(quoted_smime_cert), smime_cert);
804 if (r < 0) {
805 res = MAIL_ERROR_MEMORY;
806 goto unlink_signature;
807 }
808
809 snprintf(command, sizeof(command),
810 "openssl smime -sign -in %s -out %s -signer %s -inkey %s 2>/dev/null",
811 quoted_signed_filename, quoted_signature_filename,
812 quoted_smime_cert, quoted_smime_key);
813
814 r = system(command);
815 if (WEXITSTATUS(r) != 0) {
816 res = MAIL_ERROR_COMMAND;
817 goto unlink_signature;
818 }
819
820 /* signature part */
821
822 r = mailprivacy_get_part_from_file(privacy, 0,
823 signature_filename, &signed_mime);
824 if (r != MAIL_NO_ERROR) {
825 res = r;
826 goto unlink_signature;
827 }
828 strip_mime_headers(signed_mime);
829
830 unlink(signature_filename);
831 unlink(signed_filename);
832
833 * result = signed_mime;
834
835 return MAIL_NO_ERROR;
836
837 unlink_signature:
838 unlink(signature_filename);
839 unlink_signed:
840 unlink(signed_filename);
841 err:
842 return res;
843}
844
845
846/* ********************************************************************* */
847/* find S/MIME recipient */
848
849static int recipient_add_mb(char * recipient, size_t * len,
850 struct mailimf_mailbox * mb)
851{
852 char * filename;
853 char quoted_filename[PATH_MAX];
854 size_t buflen;
855 int r;
856
857 if (mb->mb_addr_spec == NULL)
858 return MAIL_NO_ERROR;
859
860 filename = get_cert_file(mb->mb_addr_spec);
861 if (filename == NULL)
862 return MAIL_ERROR_INVAL;
863
864 r = mail_quote_filename(quoted_filename, sizeof(quoted_filename),
865 filename);
866 if (r < 0)
867 return MAIL_ERROR_MEMORY;
868
869 buflen = strlen(quoted_filename + 1);
870 if (buflen >= * len)
871 return MAIL_ERROR_MEMORY;
872
873 strncat(recipient, quoted_filename, * len);
874 (* len) -= buflen;
875 strncat(recipient, " ", * len);
876 (* len) --;
877
878 return MAIL_NO_ERROR;
879}
880
881static int recipient_add_mb_list(char * recipient, size_t * len,
882 struct mailimf_mailbox_list * mb_list)
883{
884 clistiter * cur;
885 int r;
886
887 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
888 cur = clist_next(cur)) {
889 struct mailimf_mailbox * mb;
890
891 mb = clist_content(cur);
892
893 r = recipient_add_mb(recipient, len, mb);
894 if (r != MAIL_NO_ERROR)
895 return r;
896 }
897
898 return MAIL_NO_ERROR;
899}
900
901static int recipient_add_group(char * recipient, size_t * len,
902 struct mailimf_group * group)
903{
904 return recipient_add_mb_list(recipient, len, group->grp_mb_list);
905}
906
907static int recipient_add_addr(char * recipient, size_t * len,
908 struct mailimf_address * addr)
909{
910 int r;
911
912 switch (addr->ad_type) {
913 case MAILIMF_ADDRESS_MAILBOX:
914 r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox);
915 break;
916 case MAILIMF_ADDRESS_GROUP:
917 r = recipient_add_group(recipient, len, addr->ad_data.ad_group);
918 break;
919 default:
920 r = MAIL_ERROR_INVAL;
921 }
922
923 return r;
924}
925
926static int recipient_add_addr_list(char * recipient, size_t * len,
927 struct mailimf_address_list * addr_list)
928{
929 clistiter * cur;
930 int r;
931
932 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
933 cur = clist_next(cur)) {
934 struct mailimf_address * addr;
935
936 addr = clist_content(cur);
937
938 r = recipient_add_addr(recipient, len, addr);
939 if (r != MAIL_NO_ERROR)
940 return r;
941 }
942
943 return MAIL_NO_ERROR;
944}
945
946static int collect_smime_cert(char * recipient, size_t size,
947 struct mailimf_fields * fields)
948{
949 struct mailimf_single_fields single_fields;
950 int r;
951 size_t remaining;
952 int res;
953
954 * recipient = '\0';
955 remaining = size;
956
957 if (fields != NULL)
958 mailimf_single_fields_init(&single_fields, fields);
959
960 if (single_fields.fld_to != NULL) {
961 r = recipient_add_addr_list(recipient, &remaining,
962 single_fields.fld_to->to_addr_list);
963 if (r != MAIL_NO_ERROR) {
964 res = r;
965 goto err;
966 }
967 }
968
969 if (single_fields.fld_cc != NULL) {
970 r = recipient_add_addr_list(recipient, &remaining,
971 single_fields.fld_cc->cc_addr_list);
972 if (r != MAIL_NO_ERROR) {
973 res = r;
974 goto err;
975 }
976 }
977
978 if (single_fields.fld_bcc != NULL) {
979 if (single_fields.fld_bcc->bcc_addr_list != NULL) {
980 r = recipient_add_addr_list(recipient, &remaining,
981 single_fields.fld_bcc->bcc_addr_list);
982 if (r < 0) {
983 res = r;
984 goto err;
985 }
986 }
987 }
988
989 return MAIL_NO_ERROR;
990
991 err:
992 return res;
993}
994
995
996
997static int smime_encrypt(struct mailprivacy * privacy,
998 struct mailmime * mime, struct mailmime ** result)
999{
1000 char encrypted_filename[PATH_MAX];
1001 FILE * encrypted_f;
1002 int res;
1003 int r;
1004 int col;
1005 char decrypted_filename[PATH_MAX];
1006 FILE * decrypted_f;
1007 char command[PATH_MAX];
1008 char quoted_decrypted_filename[PATH_MAX];
1009 char quoted_encrypted_filename[PATH_MAX];
1010 struct mailmime * encrypted_mime;
1011 struct mailmime * root;
1012 struct mailimf_fields * fields;
1013 char recipient[PATH_MAX];
1014
1015 root = mime;
1016 while (root->mm_parent != NULL)
1017 root = root->mm_parent;
1018
1019 fields = NULL;
1020 if (root->mm_type == MAILMIME_MESSAGE)
1021 fields = root->mm_data.mm_message.mm_fields;
1022
1023 /* recipient */
1024 r = collect_smime_cert(recipient, sizeof(recipient), fields);
1025 if (r != MAIL_NO_ERROR) {
1026 res = r;
1027 goto err;
1028 }
1029
1030 /* part to encrypt */
1031
1032 /* encode quoted printable all text parts */
1033
1034 mailprivacy_prepare_mime(mime);
1035
1036 decrypted_f = mailprivacy_get_tmp_file(privacy,
1037 decrypted_filename,
1038 sizeof(decrypted_filename));
1039 if (decrypted_f == NULL) {
1040 res = MAIL_ERROR_FILE;
1041 goto err;
1042 }
1043
1044 col = 0;
1045 r = mailmime_write(decrypted_f, &col, mime);
1046 if (r != MAILIMF_NO_ERROR) {
1047 fclose(decrypted_f);
1048 res = MAIL_ERROR_FILE;
1049 goto unlink_decrypted;
1050 }
1051
1052 fclose(decrypted_f);
1053
1054 /* prepare destination file for encryption */
1055
1056 encrypted_f = mailprivacy_get_tmp_file(privacy,
1057 encrypted_filename,
1058 sizeof(encrypted_filename));
1059 if (encrypted_f == NULL) {
1060 res = MAIL_ERROR_FILE;
1061 goto unlink_decrypted;
1062 }
1063 fclose(encrypted_f);
1064
1065 r = mail_quote_filename(quoted_decrypted_filename,
1066 sizeof(quoted_decrypted_filename), decrypted_filename);
1067 if (r < 0) {
1068 res = MAIL_ERROR_MEMORY;
1069 goto unlink_encrypted;
1070 }
1071
1072 r = mail_quote_filename(quoted_encrypted_filename,
1073 sizeof(quoted_encrypted_filename), encrypted_filename);
1074 if (r < 0) {
1075 res = MAIL_ERROR_MEMORY;
1076 goto unlink_encrypted;
1077 }
1078
1079 snprintf(command, sizeof(command),
1080 "openssl smime -encrypt -in %s -out %s %s 2>/dev/null",
1081 quoted_decrypted_filename, quoted_encrypted_filename, recipient);
1082
1083 r = system(command);
1084 if (WEXITSTATUS(r) != 0) {
1085 res = MAIL_ERROR_COMMAND;
1086 goto unlink_encrypted;
1087 }
1088
1089 /* encrypted part */
1090
1091 r = mailprivacy_get_part_from_file(privacy, 0,
1092 encrypted_filename, &encrypted_mime);
1093 if (r != MAIL_NO_ERROR) {
1094 res = r;
1095 goto unlink_encrypted;
1096 }
1097 strip_mime_headers(encrypted_mime);
1098
1099 unlink(encrypted_filename);
1100 unlink(decrypted_filename);
1101
1102 * result = encrypted_mime;
1103
1104 return MAIL_NO_ERROR;
1105
1106 unlink_encrypted:
1107 unlink(encrypted_filename);
1108 unlink_decrypted:
1109 unlink(decrypted_filename);
1110 err:
1111 return res;
1112}
1113
1114
1115static int smime_sign_encrypt(struct mailprivacy * privacy,
1116 struct mailmime * mime, struct mailmime ** result)
1117{
1118 char encrypted_filename[PATH_MAX];
1119 FILE * encrypted_f;
1120 int res;
1121 int r;
1122 int col;
1123 char signature_filename[PATH_MAX];
1124 FILE * signature_f;
1125 char decrypted_filename[PATH_MAX];
1126 FILE * decrypted_f;
1127 char command[PATH_MAX];
1128 char quoted_decrypted_filename[PATH_MAX];
1129 char quoted_encrypted_filename[PATH_MAX];
1130 char quoted_signature_filename[PATH_MAX];
1131 struct mailmime * encrypted_mime;
1132 struct mailmime * root;
1133 struct mailimf_fields * fields;
1134 char recipient[PATH_MAX];
1135 char * smime_cert;
1136 char * smime_key;
1137 char quoted_smime_cert[PATH_MAX];
1138 char quoted_smime_key[PATH_MAX];
1139 char * email;
1140
1141 root = mime;
1142 while (root->mm_parent != NULL)
1143 root = root->mm_parent;
1144
1145 fields = NULL;
1146 if (root->mm_type == MAILMIME_MESSAGE)
1147 fields = root->mm_data.mm_message.mm_fields;
1148
1149 /* recipient */
1150 r = collect_smime_cert(recipient, sizeof(recipient), fields);
1151 if (r != MAIL_NO_ERROR) {
1152 res = r;
1153 goto err;
1154 }
1155
1156 /* get signing key */
1157
1158 email = get_first_from_addr(mime);
1159 if (email == NULL) {
1160 res = MAIL_ERROR_INVAL;
1161 goto err;
1162 }
1163
1164 smime_key = get_private_key_file(email);
1165 smime_cert = get_cert_file(email);
1166 if ((smime_cert == NULL) || (smime_key == NULL)) {
1167 res = MAIL_ERROR_INVAL;
1168 goto err;
1169 }
1170
1171 /* part to encrypt */
1172
1173 /* encode quoted printable all text parts */
1174
1175 mailprivacy_prepare_mime(mime);
1176
1177 decrypted_f = mailprivacy_get_tmp_file(privacy,
1178 decrypted_filename, sizeof(decrypted_filename));
1179 if (decrypted_f == NULL) {
1180 res = MAIL_ERROR_FILE;
1181 goto err;
1182 }
1183
1184 col = 0;
1185 r = mailmime_write(decrypted_f, &col, mime);
1186 if (r != MAILIMF_NO_ERROR) {
1187 fclose(decrypted_f);
1188 res = MAIL_ERROR_FILE;
1189 goto unlink_decrypted;
1190 }
1191
1192 fclose(decrypted_f);
1193
1194 /* prepare destination file for signature */
1195
1196 signature_f = mailprivacy_get_tmp_file(privacy,
1197 signature_filename,
1198 sizeof(signature_filename));
1199 if (signature_f == NULL) {
1200 res = MAIL_ERROR_FILE;
1201 goto unlink_decrypted;
1202 }
1203 fclose(signature_f);
1204
1205 r = mail_quote_filename(quoted_decrypted_filename,
1206 sizeof(quoted_decrypted_filename), decrypted_filename);
1207 if (r < 0) {
1208 res = MAIL_ERROR_MEMORY;
1209 goto unlink_signature;
1210 }
1211
1212 r = mail_quote_filename(quoted_signature_filename,
1213 sizeof(quoted_signature_filename), signature_filename);
1214 if (r < 0) {
1215 res = MAIL_ERROR_MEMORY;
1216 goto unlink_signature;
1217 }
1218
1219 r = mail_quote_filename(quoted_smime_key,
1220 sizeof(quoted_smime_key), smime_key);
1221 if (r < 0) {
1222 res = MAIL_ERROR_MEMORY;
1223 goto unlink_signature;
1224 }
1225
1226 r = mail_quote_filename(quoted_smime_cert,
1227 sizeof(quoted_smime_cert), smime_cert);
1228 if (r < 0) {
1229 res = MAIL_ERROR_MEMORY;
1230 goto unlink_signature;
1231 }
1232
1233 snprintf(command, sizeof(command),
1234 "openssl smime -sign -in %s -out %s -signer %s -inkey %s 2>/dev/null",
1235 quoted_decrypted_filename, quoted_signature_filename,
1236 quoted_smime_cert, quoted_smime_key);
1237
1238 r = system(command);
1239 if (WEXITSTATUS(r) != 0) {
1240 res = MAIL_ERROR_COMMAND;
1241 goto unlink_signature;
1242 }
1243
1244
1245 /* prepare destination file for encryption */
1246
1247 encrypted_f = mailprivacy_get_tmp_file(privacy,
1248 encrypted_filename,
1249 sizeof(encrypted_filename));
1250 if (encrypted_f == NULL) {
1251 res = MAIL_ERROR_FILE;
1252 goto unlink_signature;
1253 }
1254 fclose(encrypted_f);
1255
1256 r = mail_quote_filename(quoted_encrypted_filename,
1257 sizeof(quoted_encrypted_filename), encrypted_filename);
1258 if (r < 0) {
1259 res = MAIL_ERROR_MEMORY;
1260 goto unlink_encrypted;
1261 }
1262
1263 snprintf(command, sizeof(command),
1264 "openssl smime -encrypt -in %s -out %s %s 2>/dev/null",
1265 quoted_signature_filename, quoted_encrypted_filename, recipient);
1266
1267 r = system(command);
1268 if (WEXITSTATUS(r) != 0) {
1269 res = MAIL_ERROR_COMMAND;
1270 goto unlink_encrypted;
1271 }
1272
1273 /* encrypted part */
1274
1275 r = mailprivacy_get_part_from_file(privacy, 0,
1276 encrypted_filename, &encrypted_mime);
1277 if (r != MAIL_NO_ERROR) {
1278 res = r;
1279 goto unlink_encrypted;
1280 }
1281 strip_mime_headers(encrypted_mime);
1282
1283 unlink(encrypted_filename);
1284 unlink(signature_filename);
1285 unlink(decrypted_filename);
1286
1287 * result = encrypted_mime;
1288
1289 return MAIL_NO_ERROR;
1290
1291 unlink_encrypted:
1292 unlink(encrypted_filename);
1293 unlink_signature:
1294 unlink(signature_filename);
1295 unlink_decrypted:
1296 unlink(decrypted_filename);
1297 err:
1298 return res;
1299}
1300
1301
1302
1303static struct mailprivacy_encryption smime_encryption_tab[] = {
1304 /* S/MIME signed part */
1305 {
1306 .name = "signed",
1307 .description = "S/MIME signed part",
1308 .encrypt = smime_sign,
1309 },
1310
1311 /* S/MIME encrypted part */
1312
1313 {
1314 .name = "encrypted",
1315 .description = "S/MIME encrypted part",
1316 .encrypt = smime_encrypt,
1317 },
1318
1319 /* S/MIME signed & encrypted part */
1320
1321 {
1322 .name = "signed-encrypted",
1323 .description = "S/MIME signed & encrypted part",
1324 .encrypt = smime_sign_encrypt,
1325 },
1326};
1327
1328static struct mailprivacy_protocol smime_protocol = {
1329 .name = "smime",
1330 .description = "S/MIME",
1331
1332 .is_encrypted = smime_test_encrypted,
1333 .decrypt = smime_handler,
1334
1335 .encryption_count =
1336 (sizeof(smime_encryption_tab) / sizeof(smime_encryption_tab[0])),
1337
1338 .encryption_tab = smime_encryption_tab,
1339};
1340
1341int mailprivacy_smime_init(struct mailprivacy * privacy)
1342{
1343 certificates = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
1344 if (certificates == NULL)
1345 goto err;
1346
1347 private_keys = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL);
1348 if (private_keys == NULL)
1349 goto free_cert;
1350
1351 CAcert_dir[0] = '\0';
1352
1353 return mailprivacy_register(privacy, &smime_protocol);
1354
1355 free_cert:
1356 chash_free(certificates);
1357 err:
1358 return MAIL_ERROR_MEMORY;
1359}
1360
1361void mailprivacy_smime_done(struct mailprivacy * privacy)
1362{
1363 mailprivacy_unregister(privacy, &smime_protocol);
1364 chash_free(private_keys);
1365 private_keys = NULL;
1366 chash_free(certificates);
1367 certificates = NULL;
1368 if (CAfile != NULL) {
1369 unlink(CAfile);
1370 free(CAfile);
1371 }
1372 CAfile = NULL;
1373 CAcert_dir[0] = '\0';
1374}
1375
1376
1377static void strip_string(char * str)
1378{
1379 char * p;
1380 size_t len;
1381
1382 p = strchr(str, '\r');
1383 if (p != NULL)
1384 * p = 0;
1385
1386 p = strchr(str, '\n');
1387 if (p != NULL)
1388 * p = 0;
1389
1390 p = str;
1391 while ((* p == ' ') || (* p == '\t')) {
1392 p ++;
1393 }
1394
1395 len = strlen(p);
1396 memmove(str, p, len);
1397 str[len] = 0;
1398
1399 if (len == 0)
1400 return;
1401
1402 p = str;
1403 len = len - 1;
1404 while ((p[len] == ' ') || (p[len] == '\t')) {
1405 p[len] = '\0';
1406
1407 if (len == 0)
1408 break;
1409
1410 len --;
1411 }
1412}
1413
1414
1415
1416#define MAX_EMAIL_SIZE 1024
1417
1418static void set_file(chash * hash, char * email, char * filename)
1419{
1420 char * n;
1421 char buf[MAX_EMAIL_SIZE];
1422 chashdatum key;
1423 chashdatum data;
1424
1425 strncpy(buf, email, sizeof(buf));
1426 buf[sizeof(buf) - 1] = '\0';
1427 for(n = buf ; * n != '\0' ; n ++)
1428 * n = toupper((unsigned char) * n);
1429 strip_string(buf);
1430
1431 key.data = buf;
1432 key.len = strlen(buf);
1433 data.data = filename;
1434 data.len = strlen(filename) + 1;
1435
1436 chash_set(hash, &key, &data, NULL);
1437}
1438
1439static char * get_file(chash * hash, char * email)
1440{
1441 chashdatum key;
1442 chashdatum data;
1443 char buf[MAX_EMAIL_SIZE];
1444 char * n;
1445 int r;
1446
1447 strncpy(buf, email, sizeof(buf));
1448 buf[sizeof(buf) - 1] = '\0';
1449 for(n = buf ; * n != '\0' ; n ++)
1450 * n = toupper((unsigned char) * n);
1451
1452 strip_string(buf);
1453 key.data = buf;
1454 key.len = strlen(buf);
1455 r = chash_get(hash, &key, &data);
1456 if (r < 0)
1457 return NULL;
1458
1459 return data.data;
1460}
1461
1462void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy,
1463 char * directory)
1464{
1465 DIR * dir;
1466 struct dirent * ent;
1467
1468 chash_clear(certificates);
1469
1470 if (directory == NULL)
1471 return;
1472
1473 if (* directory == '\0')
1474 return;
1475
1476 strncpy(cert_dir, directory, sizeof(cert_dir));
1477 cert_dir[sizeof(cert_dir) - 1] = '\0';
1478
1479 dir = opendir(directory);
1480 if (dir == NULL)
1481 return;
1482
1483 while ((ent = readdir(dir)) != NULL) {
1484 char filename[PATH_MAX];
1485 char command[PATH_MAX];
1486 char buf[MAX_EMAIL_SIZE];
1487 FILE * p;
1488
1489 snprintf(filename, sizeof(filename),
1490 "%s/%s", directory, ent->d_name);
1491
1492 snprintf(command, sizeof(command),
1493 "openssl x509 -email -noout -in %s 2>/dev/null", filename);
1494
1495 p = popen(command, "r");
1496 if (p == NULL)
1497 continue;
1498
1499 while (fgets(buf, sizeof(buf), p) != NULL)
1500 set_file(certificates, buf, filename);
1501
1502 pclose(p);
1503 }
1504 closedir(dir);
1505}
1506
1507static char * get_cert_file(char * email)
1508{
1509 return get_file(certificates, email);
1510}
1511
1512static char * get_private_key_file(char * email)
1513{
1514 return get_file(private_keys, email);
1515}
1516
1517void mail_private_smime_clear_private_keys(struct mailprivacy * privacy)
1518{
1519 chash_clear(private_keys);
1520}
1521
1522#define MAX_BUF 1024
1523
1524void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy,
1525 char * directory)
1526{
1527 DIR * dir;
1528 struct dirent * ent;
1529 FILE * f_CA;
1530 char CA_filename[PATH_MAX];
1531
1532 if (directory == NULL)
1533 return;
1534
1535 if (* directory == '\0')
1536 return;
1537
1538 /* make a temporary file that contains all the CAs */
1539
1540 if (CAfile != NULL) {
1541 unlink(CAfile);
1542 free(CAfile);
1543 CAfile = NULL;
1544 }
1545
1546 f_CA = mailprivacy_get_tmp_file(privacy, CA_filename, sizeof(CA_filename));
1547 if (f_CA == NULL)
1548 return;
1549
1550 strncpy(CAcert_dir, directory, sizeof(CAcert_dir));
1551 CAcert_dir[sizeof(CAcert_dir) - 1] = '\0';
1552
1553 dir = opendir(directory);
1554 if (dir == NULL) {
1555 fclose(f_CA);
1556 goto unlink_CA;
1557 }
1558
1559 while ((ent = readdir(dir)) != NULL) {
1560 char filename[PATH_MAX];
1561 char command[PATH_MAX];
1562 char buf[MAX_BUF];
1563 FILE * f;
1564
1565 snprintf(filename, sizeof(filename),
1566 "%s/%s", directory, ent->d_name);
1567
1568 f = fopen(filename, "r");
1569 if (f == NULL)
1570 continue;
1571
1572 while (fgets(buf, sizeof(buf), f) != NULL)
1573 fputs(buf, f_CA);
1574
1575 fclose(f);
1576 }
1577
1578 closedir(dir);
1579
1580 fclose(f_CA);
1581
1582 CAfile = strdup(CA_filename);
1583 if (CAfile == NULL)
1584 goto unlink_CA;
1585
1586 return;
1587
1588 unlink_CA:
1589 unlink(CA_filename);
1590}
1591
1592void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy,
1593 int enabled)
1594{
1595 CA_check = enabled;
1596}
1597
1598void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy,
1599 int enabled)
1600{
1601 store_cert = enabled;
1602}
1603
1604static int get_cert_from_sig(struct mailprivacy * privacy,
1605 mailmessage * msg,
1606 struct mailmime * mime)
1607{
1608 clistiter * cur;
1609 struct mailmime * signed_mime;
1610 struct mailmime * signature_mime;
1611 int res;
1612 char signature_filename[PATH_MAX];
1613 char quoted_signature_filename[PATH_MAX];
1614 char * email;
1615 char * cert_file;
1616 char store_cert_filename[PATH_MAX];
1617 char quoted_store_cert_filename[PATH_MAX];
1618 int r;
1619 char command[PATH_MAX];
1620
1621 if (* cert_dir == '\0')
1622 return MAIL_ERROR_INVAL;
1623
1624 if (mime->mm_type != MAILMIME_MULTIPLE)
1625 return MAIL_ERROR_INVAL;
1626
1627 email = get_first_from_addr(mime);
1628 if (email == NULL)
1629 return MAIL_ERROR_INVAL;
1630
1631 cert_file = get_cert_file(email);
1632 if (cert_file != NULL)
1633 return MAIL_NO_ERROR;
1634
1635 /* get the two parts of the S/MIME message */
1636
1637 cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list);
1638 if (cur == NULL) {
1639 res = MAIL_ERROR_INVAL;
1640 goto err;
1641 }
1642
1643 signed_mime = cur->data;
1644 cur = clist_next(cur);
1645 if (cur == NULL) {
1646 res = MAIL_ERROR_INVAL;
1647 goto err;
1648 }
1649
1650 signature_mime = cur->data;
1651
1652 r = mailprivacy_fetch_decoded_to_file(privacy,
1653 signature_filename, sizeof(signature_filename),
1654 msg, signature_mime);
1655 if (r != MAILIMF_NO_ERROR) {
1656 res = r;
1657 goto err;
1658 }
1659
1660 r = mail_quote_filename(quoted_signature_filename,
1661 sizeof(quoted_signature_filename), signature_filename);
1662 if (r < 0) {
1663 res = MAIL_ERROR_MEMORY;
1664 goto unlink_signature;
1665 }
1666
1667 snprintf(store_cert_filename, sizeof(store_cert_filename),
1668 "%s/%s-cert.pem", cert_dir, email);
1669
1670 r = mail_quote_filename(quoted_store_cert_filename,
1671 sizeof(quoted_store_cert_filename), store_cert_filename);
1672 if (r < 0) {
1673 res = MAIL_ERROR_MEMORY;
1674 goto unlink_signature;
1675 }
1676
1677 snprintf(command, sizeof(command),
1678 "openssl pkcs7 -inform DER -in %s -out %s -print_certs 2>/dev/null",
1679 quoted_signature_filename, quoted_store_cert_filename);
1680
1681 r = system(command);
1682 if (WEXITSTATUS(r) != 0) {
1683 res = MAIL_ERROR_COMMAND;
1684 goto unlink_signature;
1685 }
1686
1687 unlink(signature_filename);
1688
1689 set_file(certificates, email, store_cert_filename);
1690
1691 return MAIL_NO_ERROR;
1692
1693 unlink_signature:
1694 unlink(signature_filename);
1695 err:
1696 return res;
1697}
1698
1699
1700static void set_private_key(struct mailprivacy * privacy,
1701 char * email, char * file)
1702{
1703 set_file(private_keys, email, file);
1704}
1705
1706#define PRIVATE_KEY_SUFFIX "-private-key.pem"
1707
1708void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy,
1709 char * directory)
1710{
1711 DIR * dir;
1712 struct dirent * ent;
1713
1714 chash_clear(private_keys);
1715
1716 if (directory == NULL)
1717 return;
1718
1719 if (* directory == '\0')
1720 return;
1721
1722 strncpy(private_keys_dir, directory, sizeof(private_keys_dir));
1723 private_keys_dir[sizeof(private_keys_dir) - 1] = '\0';
1724
1725 dir = opendir(directory);
1726 if (dir == NULL)
1727 return;
1728
1729 while ((ent = readdir(dir)) != NULL) {
1730 char filename[PATH_MAX];
1731 char email[PATH_MAX];
1732 char * p;
1733
1734 snprintf(filename, sizeof(filename),
1735 "%s/%s", directory, ent->d_name);
1736
1737 strncpy(email, ent->d_name, sizeof(email));
1738 email[sizeof(email) - 1] = '\0';
1739
1740 p = strstr(email, PRIVATE_KEY_SUFFIX);
1741 if (p == NULL)
1742 continue;
1743
1744 if (strlen(p) != sizeof(PRIVATE_KEY_SUFFIX) - 1)
1745 continue;
1746
1747 * p = 0;
1748
1749 if (* email == '\0')
1750 continue;
1751
1752 set_private_key(privacy, email, filename);
1753 }
1754 closedir(dir);
1755}
diff --git a/libetpan/src/engine/mailprivacy_smime.h b/libetpan/src/engine/mailprivacy_smime.h
new file mode 100644
index 0000000..85d9e40
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_smime.h
@@ -0,0 +1,84 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPRIVACY_SMIME_H
37
38#define MAILPRIVACY_SMIME_H
39
40#include <libetpan/mailprivacy_types.h>
41
42int mailprivacy_smime_init(struct mailprivacy * privacy);
43
44void mailprivacy_smime_done(struct mailprivacy * privacy);
45
46void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy,
47 char * directory);
48
49
50/*
51 set directory where certificates of authority certifications are
52 stored.
53*/
54
55void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy,
56 char * directory);
57
58
59/*
60 to disable the verification of signers certificates of a
61 signed message.
62*/
63
64void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy,
65 int enabled);
66
67
68/*
69 to store certificates of signed messages
70*/
71
72void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy,
73 int enabled);
74
75/*
76 set directory where private keys are stored.
77 name of the files in that directory must be in form :
78 [email-address]-private-key.pem
79*/
80
81void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy,
82 char * directory);
83
84#endif
diff --git a/libetpan/src/engine/mailprivacy_tools.c b/libetpan/src/engine/mailprivacy_tools.c
new file mode 100644
index 0000000..cae2ef8
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_tools.c
@@ -0,0 +1,1283 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailprivacy_tools.h"
37
38#include <stdlib.h>
39#include <string.h>
40#include <libgen.h>
41#include <unistd.h>
42#include <sys/mman.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <fcntl.h>
46#include <libetpan/mailmessage.h>
47#include <ctype.h>
48#include "mailprivacy.h"
49#include <libetpan/libetpan-config.h>
50#include <libetpan/data_message_driver.h>
51
52void mailprivacy_mime_clear(struct mailmime * mime)
53{
54 struct mailmime_data * data;
55 clistiter * cur;
56
57 switch (mime->mm_type) {
58 case MAILMIME_SINGLE:
59 data = mime->mm_data.mm_single;
60 if (data != NULL) {
61 if (data->dt_type == MAILMIME_DATA_FILE)
62 unlink(data->dt_data.dt_filename);
63 }
64 break;
65
66 case MAILMIME_MULTIPLE:
67 data = mime->mm_data.mm_multipart.mm_preamble;
68 if (data != NULL) {
69 if (data->dt_type == MAILMIME_DATA_FILE)
70 unlink(data->dt_data.dt_filename);
71 }
72 data = mime->mm_data.mm_multipart.mm_epilogue;
73 if (data != NULL) {
74 if (data->dt_type == MAILMIME_DATA_FILE)
75 unlink(data->dt_data.dt_filename);
76 }
77
78 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
79 cur != NULL ; cur = clist_next(cur)) {
80 struct mailmime * submime;
81
82 submime = clist_content(cur);
83
84 mailprivacy_mime_clear(submime);
85 }
86 break;
87
88 case MAILMIME_MESSAGE:
89 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
90 mailprivacy_mime_clear(mime->mm_data.mm_message.mm_msg_mime);
91 }
92 break;
93 }
94}
95
96
97static FILE * get_tmp_file(char * filename)
98{
99 int fd;
100 mode_t old_mask;
101 FILE * f;
102
103 old_mask = umask(0077);
104 fd = mkstemp(filename);
105 umask(old_mask);
106 if (fd == -1)
107 return NULL;
108
109 f = fdopen(fd, "r+");
110 if (f == NULL) {
111 close(fd);
112 unlink(filename);
113 }
114
115 return f;
116}
117
118FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy,
119 char * filename, size_t size)
120{
121 snprintf(filename, size, "%s/libetpan-privacy-XXXXXX", privacy->tmp_dir);
122 return get_tmp_file(filename);
123}
124
125
126static char * dup_file(struct mailprivacy * privacy,
127 char * source_filename)
128{
129 char filename[PATH_MAX];
130 FILE * dest_f;
131 int r;
132 struct stat stat_info;
133 char * dest_filename;
134 char * mapping;
135 size_t written;
136 int fd;
137
138 dest_f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename));
139 if (dest_f == NULL)
140 goto err;
141
142 dest_filename = strdup(filename);
143 if (dest_filename == NULL)
144 goto close_dest;
145
146 fd = open(source_filename, O_RDONLY);
147 if (fd < 0)
148 goto free_dest;
149
150 r = fstat(fd, &stat_info);
151 if (r < 0)
152 goto close_src;
153
154 mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
155 if (mapping == MAP_FAILED)
156 goto close_src;
157
158 written = fwrite(mapping, 1, stat_info.st_size, dest_f);
159 if (written != (size_t) stat_info.st_size)
160 goto unmap;
161
162 munmap(mapping, stat_info.st_size);
163 close(fd);
164 fclose(dest_f);
165
166 return dest_filename;
167
168 unmap:
169 munmap(mapping, stat_info.st_size);
170 close_src:
171 close(fd);
172 free_dest:
173 free(dest_filename);
174 close_dest:
175 fclose(dest_f);
176 err:
177 return NULL;
178}
179
180
181/*
182 mime_data_replace()
183
184 write a mime part to a file and change the reference of mailmime_data
185 to the file.
186*/
187
188static int mime_data_replace(struct mailprivacy * privacy,
189 int encoding_type,
190 struct mailmime_data * data)
191{
192 char filename[PATH_MAX];
193 FILE * f;
194 size_t written;
195 char * dup_filename;
196 int res;
197 int r;
198 int decoded;
199
200 if (data->dt_type != MAILMIME_DATA_TEXT) {
201 res = MAIL_NO_ERROR;
202 goto err;
203 }
204
205 f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename));
206 if (f == NULL) {
207 res = MAIL_ERROR_FILE;
208 goto err;
209 }
210
211 decoded = 0;
212 if (encoding_type != -1) {
213 char * content;
214 size_t content_len;
215 size_t cur_token;
216
217 cur_token = 0;
218 r = mailmime_part_parse(data->dt_data.dt_text.dt_data,
219 data->dt_data.dt_text.dt_length,
220 &cur_token, encoding_type, &content, &content_len);
221
222 if (r == MAILIMF_NO_ERROR) {
223 /* write decoded */
224 written = fwrite(content, 1, content_len, f);
225 if (written != content_len) {
226 fclose(f);
227 unlink(filename);
228 res = MAIL_ERROR_FILE;
229 goto err;
230 }
231 mmap_string_unref(content);
232
233 decoded = 1;
234 data->dt_encoded = 0;
235 }
236 }
237
238 if (!decoded) {
239 written = fwrite(data->dt_data.dt_text.dt_data, 1,
240 data->dt_data.dt_text.dt_length, f);
241 if (written != data->dt_data.dt_text.dt_length) {
242 fclose(f);
243 unlink(filename);
244 res = MAIL_ERROR_FILE;
245 goto err;
246 }
247 }
248
249 fclose(f);
250
251 dup_filename = strdup(filename);
252 if (dup_filename == NULL) {
253 unlink(filename);
254 res = MAIL_ERROR_MEMORY;
255 goto err;
256 }
257
258 data->dt_type = MAILMIME_DATA_FILE;
259 data->dt_data.dt_filename = dup_filename;
260
261 return MAIL_NO_ERROR;
262
263 err:
264 return res;
265}
266
267
268/*
269 recursive_replace_single_parts()
270
271 write all parts of the given mime part to file.
272*/
273
274static int recursive_replace_single_parts(struct mailprivacy * privacy,
275 struct mailmime * mime)
276{
277 int r;
278 int res;
279 clistiter * cur;
280
281 mime->mm_mime_start = NULL;
282
283 switch(mime->mm_type) {
284 case MAILMIME_SINGLE:
285 if (mime->mm_data.mm_single != NULL) {
286 int encoding_type;
287 struct mailmime_single_fields single_fields;
288
289 mailmime_single_fields_init(&single_fields, mime->mm_mime_fields,
290 mime->mm_content_type);
291
292 if (single_fields.fld_encoding != NULL)
293 encoding_type = single_fields.fld_encoding->enc_type;
294 else
295 encoding_type = -1;
296
297 r = mime_data_replace(privacy, encoding_type, mime->mm_data.mm_single);
298 if (r != MAIL_NO_ERROR) {
299 res = r;
300 goto err;
301 }
302 }
303 break;
304
305 case MAILMIME_MULTIPLE:
306 if (mime->mm_data.mm_multipart.mm_preamble != NULL) {
307 r = mime_data_replace(privacy, -1,
308 mime->mm_data.mm_multipart.mm_preamble);
309 if (r != MAIL_NO_ERROR) {
310 res = r;
311 goto err;
312 }
313 }
314
315 if (mime->mm_data.mm_multipart.mm_epilogue != NULL) {
316 r = mime_data_replace(privacy, -1,
317 mime->mm_data.mm_multipart.mm_epilogue);
318 if (r != MAIL_NO_ERROR) {
319 res = r;
320 goto err;
321 }
322 }
323
324 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
325 cur != NULL ; cur = clist_next(cur)) {
326 struct mailmime * child;
327
328 child = clist_content(cur);
329
330 r = recursive_replace_single_parts(privacy, child);
331 if (r != MAIL_NO_ERROR) {
332 res = r;
333 goto err;
334 }
335 }
336
337 break;
338
339 case MAILMIME_MESSAGE:
340 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
341 r = recursive_replace_single_parts(privacy,
342 mime->mm_data.mm_message.mm_msg_mime);
343 if (r != MAIL_NO_ERROR) {
344 res = r;
345 goto err;
346 }
347 }
348 break;
349 }
350
351 return MAIL_NO_ERROR;
352
353 err:
354 return res;
355}
356
357/*
358 mailprivacy_get_mime()
359
360 parse the message in MIME structure,
361 all single MIME parts are stored in files.
362
363 privacy can be set to NULL to disable privacy check.
364*/
365
366int mailprivacy_get_mime(struct mailprivacy * privacy,
367 int check_privacy,
368 char * content, size_t content_len,
369 struct mailmime ** result_mime)
370{
371 struct mailmime * mime;
372 mailmessage * msg;
373 int r;
374 int res;
375
376#if 0
377 int check_privacy;
378
379 check_privacy = (privacy != NULL);
380#endif
381
382 /*
383 use message data driver, get bodystructure and
384 convert all the data part in MAILMIME_SINGLE to files.
385 */
386
387 msg = data_message_init(content, content_len);
388 if (msg == NULL) {
389 res = MAIL_ERROR_MEMORY;
390 goto err;
391 }
392
393#if 0
394 if (msg->mime == NULL) {
395 if (check_privacy) {
396 r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime);
397 }
398 else {
399 /*
400 don't use etpan_msg_get_bodystructure because it is not useful
401 and to avoid loops due to security part
402 */
403 r = mailmessage_get_bodystructure(msg, &mime);
404 }
405 }
406 else {
407 mime = msg->mime;
408 }
409#endif
410
411 if (check_privacy)
412 r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime);
413 else
414 r = mailmessage_get_bodystructure(msg, &mime);
415 if (r != MAIL_NO_ERROR) {
416 res = r;
417 goto free_msg;
418 }
419
420 /*
421 should be done so that the MIME structure need not to be unregistered.
422 */
423 mailprivacy_recursive_unregister_mime(privacy, mime);
424
425 r = recursive_replace_single_parts(privacy, mime);
426 if (r != MAIL_NO_ERROR) {
427 res = r;
428 goto clear_mime;
429 }
430
431 data_message_detach_mime(msg);
432#if 0
433 if (check_privacy)
434 mailprivacy_msg_flush(privacy, msg);
435 else
436 mailmessage_flush(msg);
437#endif
438 mailprivacy_msg_flush(privacy, msg);
439 mailmessage_free(msg);
440
441 * result_mime = mime;
442
443 return MAIL_NO_ERROR;
444
445 clear_mime:
446 mailprivacy_mime_clear(mime);
447 mailprivacy_msg_flush(privacy, msg);
448 free_msg:
449 mailmessage_free(msg);
450 err:
451 return res;
452}
453
454#ifndef LIBETPAN_SYSTEM_BASENAME
455static char * libetpan_basename(char * filename)
456{
457 char * next;
458 char * p;
459
460 p = filename;
461 next = strchr(p, '/');
462
463 while (next != NULL) {
464 p = next;
465 next = strchr(p + 1, '/');
466 }
467
468 if (p == filename)
469 return filename;
470 else
471 return p + 1;
472}
473#else
474#define libetpan_basename(a) basename(a)
475#endif
476
477struct mailmime *
478mailprivacy_new_file_part(struct mailprivacy * privacy,
479 char * filename,
480 char * default_content_type, int default_encoding)
481{
482 char basename_buf[PATH_MAX];
483 char * name;
484 struct mailmime_mechanism * encoding;
485 struct mailmime_content * content;
486 struct mailmime * mime;
487 int r;
488 char * dup_filename;
489 struct mailmime_fields * mime_fields;
490 int encoding_type;
491 char * content_type_str;
492 int do_encoding;
493
494 if (filename != NULL) {
495 strncpy(basename_buf, filename, PATH_MAX);
496 name = libetpan_basename(basename_buf);
497 }
498 else {
499 name = NULL;
500 }
501
502 encoding = NULL;
503
504 /* default content-type */
505 if (default_content_type == NULL)
506 content_type_str = "application/octet-stream";
507 else
508 content_type_str = default_content_type;
509
510 content = mailmime_content_new_with_str(content_type_str);
511 if (content == NULL) {
512 goto free_content;
513 }
514
515 do_encoding = 1;
516 if (content->ct_type->tp_type == MAILMIME_TYPE_COMPOSITE_TYPE) {
517 struct mailmime_composite_type * composite;
518
519 composite = content->ct_type->tp_data.tp_composite_type;
520
521 switch (composite->ct_type) {
522 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
523 if (strcasecmp(content->ct_subtype, "rfc822") == 0)
524 do_encoding = 0;
525 break;
526
527 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
528 do_encoding = 0;
529 break;
530 }
531 }
532
533 if (do_encoding) {
534 if (default_encoding == -1)
535 encoding_type = MAILMIME_MECHANISM_BASE64;
536 else
537 encoding_type = default_encoding;
538
539 /* default Content-Transfer-Encoding */
540 encoding = mailmime_mechanism_new(encoding_type, NULL);
541 if (encoding == NULL) {
542 goto free_content;
543 }
544 }
545
546 mime_fields = mailmime_fields_new_with_data(encoding,
547 NULL, NULL, NULL, NULL);
548 if (mime_fields == NULL) {
549 goto free_content;
550 }
551
552 mime = mailmime_new_empty(content, mime_fields);
553 if (mime == NULL) {
554 goto free_mime_fields;
555 }
556
557 if ((filename != NULL) && (mime->mm_type == MAILMIME_SINGLE)) {
558 /*
559 duplicates the file so that the file can be deleted when
560 the MIME part is done
561 */
562 dup_filename = dup_file(privacy, filename);
563 if (dup_filename == NULL) {
564 goto free_mime;
565 }
566
567 r = mailmime_set_body_file(mime, dup_filename);
568 if (r != MAILIMF_NO_ERROR) {
569 free(dup_filename);
570 goto free_mime;
571 }
572 }
573
574 return mime;
575
576 free_mime:
577 mailmime_free(mime);
578 goto err;
579 free_mime_fields:
580 mailmime_fields_free(mime_fields);
581 mailmime_content_free(content);
582 goto err;
583 free_content:
584 if (encoding != NULL)
585 mailmime_mechanism_free(encoding);
586 if (content != NULL)
587 mailmime_content_free(content);
588 err:
589 return NULL;
590}
591
592
593int mailmime_substitute(struct mailmime * old_mime,
594 struct mailmime * new_mime)
595{
596 struct mailmime * parent;
597
598 parent = old_mime->mm_parent;
599 if (parent == NULL)
600 return MAIL_ERROR_INVAL;
601
602 if (old_mime->mm_parent_type == MAILMIME_MESSAGE)
603 parent->mm_data.mm_message.mm_msg_mime = new_mime;
604 else /* MAILMIME_MULTIPLE */
605 old_mime->mm_multipart_pos->data = new_mime;
606 new_mime->mm_parent = parent;
607 new_mime->mm_parent_type = old_mime->mm_parent_type;
608
609 /* detach old_mime */
610 old_mime->mm_parent = NULL;
611 old_mime->mm_parent_type = MAILMIME_NONE;
612
613 return MAIL_NO_ERROR;
614}
615
616
617
618/* write mime headers and body to a file, CR LF fixed */
619
620int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy,
621 char * filename, size_t size,
622 mailmessage * msg, struct mailmime * mime)
623{
624 int r;
625 int res;
626 FILE * f;
627 char * content;
628 size_t content_len;
629 int col;
630
631 if (mime->mm_parent_type == MAILMIME_NONE) {
632 res = MAIL_ERROR_INVAL;
633 goto err;
634 }
635
636 f = mailprivacy_get_tmp_file(privacy, filename, size);
637 if (f == NULL) {
638 res = MAIL_ERROR_FETCH;
639 goto err;
640 }
641
642 r = mailprivacy_msg_fetch_section_mime(privacy, msg, mime,
643 &content, &content_len);
644 if (r != MAIL_NO_ERROR) {
645 res = MAIL_ERROR_FETCH;
646 goto close;
647 }
648
649 col = 0;
650 r = mailimf_string_write(f, &col, content, content_len);
651 mailprivacy_msg_fetch_result_free(privacy, msg, content);
652 if (r != MAILIMF_NO_ERROR) {
653 res = r;
654 goto close;
655 }
656
657 r = mailprivacy_msg_fetch_section(privacy, msg, mime,
658 &content, &content_len);
659 if (r != MAIL_NO_ERROR) {
660 res = MAIL_ERROR_FETCH;
661 goto close;
662 }
663
664 r = mailimf_string_write(f, &col, content, content_len);
665 mailprivacy_msg_fetch_result_free(privacy, msg, content);
666 if (r != MAILIMF_NO_ERROR) {
667 res = r;
668 goto close;
669 }
670
671 fclose(f);
672
673 return MAIL_NO_ERROR;
674
675 close:
676 fclose(f);
677 unlink(filename);
678 err:
679 return res;
680}
681
682
683int mailprivacy_get_part_from_file(struct mailprivacy * privacy,
684 int check_security, char * filename,
685 struct mailmime ** result_mime)
686{
687 int fd;
688 struct mailmime * mime;
689 int r;
690 struct stat stat_info;
691 int res;
692 char * mapping;
693
694 fd = open(filename, O_RDONLY);
695 if (fd < 0) {
696 res = MAIL_ERROR_FILE;
697 goto err;
698 }
699
700 r = fstat(fd, &stat_info);
701 if (r < 0) {
702 res = MAIL_ERROR_FILE;
703 goto close;
704 }
705
706 mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
707 if (mapping == MAP_FAILED) {
708 res = MAIL_ERROR_FILE;
709 goto close;
710 }
711
712 /* check recursive parts if privacy is set */
713 r = mailprivacy_get_mime(privacy, check_security,
714 mapping, stat_info.st_size, &mime);
715 if (r != MAIL_NO_ERROR) {
716 res = r;
717 goto unmap;
718 }
719
720 if (mime->mm_type == MAILMIME_MESSAGE) {
721 struct mailmime * submime;
722
723 submime = mime->mm_data.mm_message.mm_msg_mime;
724 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
725 mailmime_remove_part(submime);
726 mailmime_free(mime);
727
728 mime = submime;
729 }
730 }
731
732 munmap(mapping, stat_info.st_size);
733
734 close(fd);
735
736 * result_mime = mime;
737
738 return MAIL_NO_ERROR;
739
740 unmap:
741 munmap(mapping, stat_info.st_size);
742 close:
743 close(fd);
744 err:
745 return res;
746}
747
748int mail_quote_filename(char * result, size_t size, char * path)
749{
750 char * p;
751 char * result_p;
752 size_t remaining;
753
754 result_p = result;
755 remaining = size;
756
757 for(p = path ; * p != '\0' ; p ++) {
758
759 if (isalpha(* p) || isdigit(* p) || (* p == '/')) {
760 if (remaining > 0) {
761 * result_p = * p;
762 result_p ++;
763 remaining --;
764 }
765 else {
766 result[size - 1] = '\0';
767 return -1;
768 }
769 }
770 else {
771 if (remaining >= 2) {
772 * result_p = '\\';
773 result_p ++;
774 * result_p = * p;
775 result_p ++;
776 remaining -= 2;
777 }
778 else {
779 result[size - 1] = '\0';
780 return -1;
781 }
782 }
783 }
784 if (remaining > 0) {
785 * result_p = '\0';
786 }
787 else {
788 result[size - 1] = '\0';
789 return -1;
790 }
791
792 return 0;
793}
794
795
796static void prepare_mime_single(struct mailmime * mime)
797{
798 struct mailmime_single_fields single_fields;
799 int encoding;
800 int r;
801
802 if (mime->mm_mime_fields != NULL) {
803 mailmime_single_fields_init(&single_fields, mime->mm_mime_fields,
804 mime->mm_content_type);
805 if (single_fields.fld_encoding != NULL) {
806 encoding = single_fields.fld_encoding->enc_type;
807 switch (encoding) {
808 case MAILMIME_MECHANISM_8BIT:
809 case MAILMIME_MECHANISM_7BIT:
810 case MAILMIME_MECHANISM_BINARY:
811 single_fields.fld_encoding->enc_type =
812 MAILMIME_MECHANISM_QUOTED_PRINTABLE;
813 break;
814 }
815 }
816 else {
817 struct mailmime_mechanism * mechanism;
818 struct mailmime_field * field;
819
820 mechanism =
821 mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL);
822 if (mechanism == NULL)
823 return;
824
825 field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING,
826 NULL, mechanism, NULL, NULL, 0, NULL, NULL);
827 if (field == NULL) {
828 mailmime_mechanism_free(mechanism);
829 return;
830 }
831
832 r = clist_append(mime->mm_mime_fields->fld_list, field);
833 if (r < 0) {
834 mailmime_field_free(field);
835 return;
836 }
837 }
838 }
839
840 if (mime->mm_type == MAILMIME_SINGLE) {
841 switch (mime->mm_data.mm_single->dt_encoding) {
842 case MAILMIME_MECHANISM_8BIT:
843 case MAILMIME_MECHANISM_7BIT:
844 case MAILMIME_MECHANISM_BINARY:
845 mime->mm_data.mm_single->dt_encoding =
846 MAILMIME_MECHANISM_QUOTED_PRINTABLE;
847 mime->mm_data.mm_single->dt_encoded = 0;
848 break;
849 }
850 }
851}
852
853/*
854 mailprivacy_prepare_mime()
855
856 we assume we built ourself the message.
857*/
858
859void mailprivacy_prepare_mime(struct mailmime * mime)
860{
861 clistiter * cur;
862
863 switch (mime->mm_type) {
864 case MAILMIME_SINGLE:
865 if (mime->mm_data.mm_single != NULL) {
866 prepare_mime_single(mime);
867 }
868 break;
869
870 case MAILMIME_MULTIPLE:
871 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
872 cur != NULL ; cur = clist_next(cur)) {
873 struct mailmime * child;
874
875 child = clist_content(cur);
876
877 mailprivacy_prepare_mime(child);
878 }
879 break;
880
881 case MAILMIME_MESSAGE:
882 if (mime->mm_data.mm_message.mm_msg_mime) {
883 mailprivacy_prepare_mime(mime->mm_data.mm_message.mm_msg_mime);
884 }
885 break;
886 }
887}
888
889
890char * mailprivacy_dup_imf_file(struct mailprivacy * privacy,
891 char * source_filename)
892{
893 char filename[PATH_MAX];
894 FILE * dest_f;
895 int r;
896 struct stat stat_info;
897 char * dest_filename;
898 char * mapping;
899 int fd;
900 int col;
901
902 dest_f = mailprivacy_get_tmp_file(privacy,
903 filename, sizeof(filename));
904 if (dest_f == NULL)
905 goto err;
906
907 dest_filename = strdup(filename);
908 if (dest_filename == NULL)
909 goto close_dest;
910
911 fd = open(source_filename, O_RDONLY);
912 if (fd < 0)
913 goto free_dest;
914
915 r = fstat(fd, &stat_info);
916 if (r < 0)
917 goto close_src;
918
919 mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
920 if (mapping == MAP_FAILED)
921 goto close_src;
922
923 col = 0;
924 r = mailimf_string_write(dest_f, &col, mapping, stat_info.st_size);
925 if (r != MAILIMF_NO_ERROR)
926 goto unmap;
927
928 munmap(mapping, stat_info.st_size);
929 close(fd);
930 fclose(dest_f);
931
932 return dest_filename;
933
934 unmap:
935 munmap(mapping, stat_info.st_size);
936 close_src:
937 close(fd);
938 free_dest:
939 free(dest_filename);
940 close_dest:
941 fclose(dest_f);
942 err:
943 return NULL;
944}
945
946/* TODO : better function to duplicate mime fields, currenly such inelegant */
947
948struct mailmime_fields *
949mailprivacy_mime_fields_dup(struct mailprivacy * privacy,
950 struct mailmime_fields * mime_fields)
951{
952 FILE * f;
953 char tmp_file[PATH_MAX];
954 int col;
955 int r;
956 struct mailmime_fields * dup_mime_fields;
957 int fd;
958 char * mapping;
959 struct stat stat_info;
960 struct mailimf_fields * fields;
961 size_t cur_token;
962
963 f = mailprivacy_get_tmp_file(privacy, tmp_file, sizeof(tmp_file));
964 if (f == NULL)
965 goto err;
966
967 col = 0;
968 r = mailmime_fields_write(f, &col, mime_fields);
969 if (r != MAILIMF_NO_ERROR)
970 goto unlink;
971
972 fflush(f);
973
974 fd = fileno(f);
975 if (fd == -1)
976 goto unlink;
977
978 r = fstat(fd, &stat_info);
979 if (r < 0)
980 goto unlink;
981
982 mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
983 if (mapping == MAP_FAILED)
984 goto unlink;
985
986 cur_token = 0;
987 r = mailimf_optional_fields_parse(mapping, stat_info.st_size,
988 &cur_token, &fields);
989 if (r != MAILIMF_NO_ERROR)
990 goto unmap;
991
992 r = mailmime_fields_parse(fields, &dup_mime_fields);
993 mailimf_fields_free(fields);
994 if (r != MAILIMF_NO_ERROR)
995 goto unmap;
996
997 munmap(mapping, stat_info.st_size);
998 fclose(f);
999 unlink(tmp_file);
1000
1001 return dup_mime_fields;
1002
1003 unmap:
1004 munmap(mapping, stat_info.st_size);
1005 unlink:
1006 fclose(f);
1007 unlink(tmp_file);
1008 err:
1009 return NULL;
1010}
1011
1012
1013
1014struct mailmime_parameter *
1015mailmime_parameter_dup(struct mailmime_parameter * param)
1016{
1017 char * name;
1018 char * value;
1019 struct mailmime_parameter * dup_param;
1020
1021 name = strdup(param->pa_name);
1022 if (name == NULL)
1023 goto err;
1024
1025 value = strdup(param->pa_value);
1026 if (value == NULL)
1027 goto free_name;
1028
1029 dup_param = mailmime_parameter_new(name, value);
1030 if (dup_param == NULL)
1031 goto free_value;
1032
1033 return dup_param;
1034
1035 free_value:
1036 free(value);
1037 free_name:
1038 free(name);
1039 err:
1040 return NULL;
1041}
1042
1043struct mailmime_composite_type *
1044mailmime_composite_type_dup(struct mailmime_composite_type * composite_type)
1045{
1046 struct mailmime_composite_type * dup_composite;
1047 char * token;
1048
1049 token = NULL;
1050 if (composite_type->ct_token != NULL) {
1051 token = strdup(composite_type->ct_token);
1052 if (token == NULL)
1053 goto err;
1054 }
1055
1056 dup_composite = mailmime_composite_type_new(composite_type->ct_type, token);
1057 if (dup_composite == NULL)
1058 goto free_token;
1059
1060 return dup_composite;
1061
1062 free_token:
1063 if (token != NULL)
1064 free(token);
1065 err:
1066 return NULL;
1067}
1068
1069struct mailmime_discrete_type *
1070mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type)
1071{
1072 struct mailmime_discrete_type * dup_discrete;
1073 char * extension;
1074
1075 extension = NULL;
1076 if (discrete_type->dt_extension != NULL) {
1077 extension = strdup(discrete_type->dt_extension);
1078 if (extension == NULL)
1079 goto err;
1080 }
1081
1082 dup_discrete = mailmime_discrete_type_new(discrete_type->dt_type, extension);
1083 if (dup_discrete == NULL)
1084 goto free_extension;
1085
1086 return dup_discrete;
1087
1088 free_extension:
1089 if (extension != NULL)
1090 free(extension);
1091 err:
1092 return NULL;
1093}
1094
1095struct mailmime_type * mailmime_type_dup(struct mailmime_type * type)
1096{
1097 struct mailmime_type * dup_type;
1098 struct mailmime_discrete_type * discrete_type;
1099 struct mailmime_composite_type * composite_type;
1100
1101 discrete_type = NULL;
1102 composite_type = NULL;
1103 switch (type->tp_type) {
1104 case MAILMIME_TYPE_DISCRETE_TYPE:
1105 discrete_type =
1106 mailmime_discrete_type_dup(type->tp_data.tp_discrete_type);
1107 if (discrete_type == NULL)
1108 goto err;
1109 break;
1110
1111 composite_type =
1112 mailmime_composite_type_dup(type->tp_data.tp_composite_type);
1113 if (composite_type == NULL)
1114 goto free_discrete;
1115 }
1116
1117 dup_type = mailmime_type_new(type->tp_type, discrete_type, composite_type);
1118 if (dup_type == NULL)
1119 goto free_composite;
1120
1121 return dup_type;
1122
1123 free_composite:
1124 if (composite_type != NULL)
1125 mailmime_composite_type_free(composite_type);
1126 free_discrete:
1127 if (discrete_type != NULL)
1128 mailmime_discrete_type_free(discrete_type);
1129 err:
1130 return NULL;
1131}
1132
1133struct mailmime_content *
1134mailmime_content_dup(struct mailmime_content * content)
1135{
1136 clist * list;
1137 struct mailmime_type * type;
1138 int r;
1139 struct mailmime_content * dup_content;
1140 char * subtype;
1141
1142 type = mailmime_type_dup(content->ct_type);
1143 if (type == NULL)
1144 goto err;
1145
1146 subtype = strdup(content->ct_subtype);
1147 if (subtype == NULL)
1148 goto free_type;
1149
1150 list = clist_new();
1151 if (list == NULL)
1152 goto free_subtype;
1153
1154 if (content->ct_parameters != NULL) {
1155 clistiter * cur;
1156
1157 for(cur = clist_begin(content->ct_parameters) ;
1158 cur != NULL ; cur = clist_next(cur)) {
1159 struct mailmime_parameter * param;
1160
1161 param = mailmime_parameter_dup(clist_content(cur));
1162 if (param == NULL)
1163 goto free_list;
1164
1165 r = clist_append(list, param);
1166 if (r < 0) {
1167 mailmime_parameter_free(param);
1168 goto free_list;
1169 }
1170 }
1171 }
1172
1173 dup_content = mailmime_content_new(type, subtype, list);
1174 if (dup_content == NULL)
1175 goto free_list;
1176
1177 return dup_content;
1178
1179 free_list:
1180 clist_foreach(list, (clist_func) mailmime_parameter_free, NULL);
1181 free_subtype:
1182 free(subtype);
1183 free_type:
1184 mailmime_type_free(type);
1185 err:
1186 return NULL;
1187}
1188
1189
1190struct mailmime_parameter *
1191mailmime_param_new_with_data(char * name, char * value)
1192{
1193 char * param_name;
1194 char * param_value;
1195 struct mailmime_parameter * param;
1196
1197 param_name = strdup(name);
1198 if (param_name == NULL)
1199 goto err;
1200
1201 param_value = strdup(value);
1202 if (param_value == NULL)
1203 goto free_name;
1204
1205 param = mailmime_parameter_new(param_name, param_value);
1206 if (param == NULL)
1207 goto free_value;
1208
1209 return param;
1210
1211 free_value:
1212 free(param_value);
1213 free_name:
1214 free(param_name);
1215 err:
1216 return NULL;
1217}
1218
1219
1220int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy,
1221 char * filename, size_t size,
1222 mailmessage * msg, struct mailmime * mime)
1223{
1224 int r;
1225 int res;
1226 FILE * f;
1227 char * content;
1228 size_t content_len;
1229 size_t written;
1230 struct mailmime_single_fields single_fields;
1231 int encoding;
1232 size_t cur_token;
1233 char * parsed_content;
1234 size_t parsed_content_len;
1235
1236 mailmime_single_fields_init(&single_fields, mime->mm_mime_fields,
1237 mime->mm_content_type);
1238 if (single_fields.fld_encoding != NULL)
1239 encoding = single_fields.fld_encoding->enc_type;
1240 else
1241 encoding = MAILMIME_MECHANISM_8BIT;
1242
1243 r = mailprivacy_msg_fetch_section(privacy, msg, mime,
1244 &content, &content_len);
1245 if (r != MAIL_NO_ERROR) {
1246 res = MAIL_ERROR_FETCH;
1247 goto err;
1248 }
1249
1250 cur_token = 0;
1251 r = mailmime_part_parse(content, content_len, &cur_token,
1252 encoding, &parsed_content, &parsed_content_len);
1253 mailprivacy_msg_fetch_result_free(privacy, msg, content);
1254 if (r != MAILIMF_NO_ERROR) {
1255 res = MAIL_ERROR_PARSE;
1256 goto err;
1257 }
1258
1259 f = mailprivacy_get_tmp_file(privacy, filename, size);
1260 if (f == NULL) {
1261 res = MAIL_ERROR_FETCH;
1262 goto free_fetch;
1263 }
1264 written = fwrite(parsed_content, 1, parsed_content_len, f);
1265 if (written != parsed_content_len) {
1266 res = MAIL_ERROR_FILE;
1267 goto close;
1268 }
1269 fclose(f);
1270
1271 mmap_string_unref(parsed_content);
1272
1273 return MAIL_NO_ERROR;
1274
1275 close:
1276 fclose(f);
1277 unlink(filename);
1278 free_fetch:
1279 mmap_string_unref(parsed_content);
1280 err:
1281 return res;
1282}
1283
diff --git a/libetpan/src/engine/mailprivacy_tools.h b/libetpan/src/engine/mailprivacy_tools.h
new file mode 100644
index 0000000..1bf27c4
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_tools.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_TOOLS_H
37
38#define MAIL_PRIVACY_TOOLS_H
39
40#include <libetpan/mailmessage.h>
41#include <libetpan/mailprivacy_types.h>
42
43void mailprivacy_mime_clear(struct mailmime * mime);
44
45FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy,
46 char * filename, size_t size);
47
48int mailprivacy_get_mime(struct mailprivacy * privacy,
49 int check_privacy,
50 char * content, size_t content_len,
51 struct mailmime ** result_mime);
52
53struct mailmime *
54mailprivacy_new_file_part(struct mailprivacy * privacy,
55 char * filename,
56 char * default_content_type, int default_encoding);
57
58int mailmime_substitute(struct mailmime * old_mime,
59 struct mailmime * new_mime);
60
61int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy,
62 char * filename, size_t size,
63 mailmessage * msg, struct mailmime * mime);
64
65int mailprivacy_get_part_from_file(struct mailprivacy * privacy,
66 int check_privacy,
67 char * filename,
68 struct mailmime ** result_mime);
69
70int mail_quote_filename(char * result, size_t size, char * path);
71
72void mailprivacy_prepare_mime(struct mailmime * mime);
73
74char * mailprivacy_dup_imf_file(struct mailprivacy * privacy,
75 char * source_filename);
76
77struct mailmime_fields *
78mailprivacy_mime_fields_dup(struct mailprivacy * privacy,
79 struct mailmime_fields * mime_fields);
80
81struct mailmime_parameter *
82mailmime_parameter_dup(struct mailmime_parameter * param);
83
84struct mailmime_composite_type *
85mailmime_composite_type_dup(struct mailmime_composite_type * composite_type);
86
87struct mailmime_discrete_type *
88mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type);
89
90struct mailmime_type * mailmime_type_dup(struct mailmime_type * type);
91
92struct mailmime_content *
93mailmime_content_dup(struct mailmime_content * content);
94
95struct mailmime_parameter *
96mailmime_param_new_with_data(char * name, char * value);
97
98int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy,
99 char * filename, size_t size,
100 mailmessage * msg, struct mailmime * mime);
101
102#endif
diff --git a/libetpan/src/engine/mailprivacy_types.h b/libetpan/src/engine/mailprivacy_types.h
new file mode 100644
index 0000000..e53f226
--- a/dev/null
+++ b/libetpan/src/engine/mailprivacy_types.h
@@ -0,0 +1,82 @@
1/*
2 * libEtPan! -- a mail library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAIL_PRIVACY_TYPES_H
37
38#define MAIL_PRIVACY_TYPES_H
39
40#include <libetpan/chash.h>
41#include <libetpan/carray.h>
42#include <libetpan/mailmessage.h>
43#include <libetpan/mailmime.h>
44
45struct mailprivacy {
46 char * tmp_dir; /* working tmp directory */
47 chash * msg_ref; /* mailmessage => present or not */
48 chash * mmapstr; /* mmapstring => present or not present */
49 chash * mime_ref; /* mime => present or not */
50 carray * protocols;
51 int make_alternative;
52 /* if make_alternative is 0, replaces the part with decrypted
53 part, if 1, adds a multipart/alternative and put the decrypted
54 and encrypted part as subparts.
55 */
56};
57
58struct mailprivacy_encryption {
59 char * name;
60 char * description;
61
62 int (* encrypt)(struct mailprivacy *,
63 struct mailmime *, struct mailmime **);
64};
65
66struct mailprivacy_protocol {
67 char * name;
68 char * description;
69
70 /* introduce to easy the port to sylpheed */
71 int (* is_encrypted)(struct mailprivacy *,
72 mailmessage *, struct mailmime *);
73
74 int (* decrypt)(struct mailprivacy *,
75 mailmessage *, struct mailmime *,
76 struct mailmime **);
77
78 int encryption_count;
79 struct mailprivacy_encryption * encryption_tab;
80};
81
82#endif
diff --git a/libetpan/src/low-level/imap/TODO b/libetpan/src/low-level/imap/TODO
new file mode 100644
index 0000000..a787a3b
--- a/dev/null
+++ b/libetpan/src/low-level/imap/TODO
@@ -0,0 +1,4 @@
1- literal data send progress
2- implement draft-16 (rfc 2822 things)
3- more efficient parser
4
diff --git a/libetpan/src/low-level/imap/mailimap.c b/libetpan/src/low-level/imap/mailimap.c
new file mode 100644
index 0000000..ef38413
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap.c
@@ -0,0 +1,2164 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap.h"
37#include "mailimap_parser.h"
38#include "mailimap_sender.h"
39#include "mail.h"
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#ifdef DEBUG
46#include "mailimap_print.h"
47#endif
48
49/*
50 RFC 2060 : IMAP4rev1
51 draft-crispin-imapv-15
52 RFC 2222 : Simple Authentication and Security Layer
53
542061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996.
55 (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL)
56
572062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin.
58 December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL)
59
602086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925
61 bytes) (Status: PROPOSED STANDARD)
62
632087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542
64 bytes) (Status: PROPOSED STANDARD)
65
662088 IMAP4 non-synchronizing literals. J. Myers. January 1997.
67 (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD)
68
692177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes)
70 (Status: PROPOSED STANDARD)
71
722180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997.
73 (Format: TXT=24750 bytes) (Status: INFORMATIONAL)
74
752192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426
76 bytes) (Status: PROPOSED STANDARD)
77
782193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format:
79 TXT=16248 bytes) (Status: PROPOSED STANDARD)
80
812195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J.
82 Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468
83 bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD)
84
852221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251
86 bytes) (Status: PROPOSED STANDARD)
87
882342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format:
89 TXT=19489 bytes) (Status: PROPOSED STANDARD)
90
912359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862
92 bytes) (Status: PROPOSED STANDARD)
93
942595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999.
95 (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD)
96
972683 IMAP4 Implementation Recommendations. B. Leiba. September 1999.
98 (Format: TXT=56300 bytes) (Status: INFORMATIONAL)
99
1002971 IMAP4 ID extension. T. Showalter. October 2000. (Format:
101 TXT=14670 bytes) (Status: PROPOSED STANDARD)
102
103http://www.ietf.org/ids.by.wg/imapext.html
104*/
105
106static char * read_line(mailimap * session);
107
108static int send_current_tag(mailimap * session);
109
110static int parse_response(mailimap * session,
111 struct mailimap_response ** result);
112
113static int parse_greeting(mailimap * session,
114 struct mailimap_greeting ** result);
115
116
117/* struct mailimap_response_info * */
118
119static void resp_text_store(mailimap * session,
120 struct mailimap_resp_text *
121 resp_text)
122{
123 struct mailimap_resp_text_code * resp_text_code;
124
125 resp_text_code = resp_text->rsp_code;
126
127 if (resp_text_code != NULL) {
128 switch (resp_text_code->rc_type) {
129 case MAILIMAP_RESP_TEXT_CODE_ALERT:
130 if (session->imap_response_info)
131 if (session->imap_response_info->rsp_alert != NULL)
132 free(session->imap_response_info->rsp_alert);
133 session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text);
134 break;
135
136 case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
137 if (session->imap_response_info) {
138 if (session->imap_response_info->rsp_badcharset != NULL) {
139 clist_foreach(resp_text_code->rc_data.rc_badcharset,
140 (clist_func) mailimap_astring_free, NULL);
141 clist_free(resp_text_code->rc_data.rc_badcharset);
142 }
143 session->imap_response_info->rsp_badcharset =
144 resp_text_code->rc_data.rc_badcharset;
145 resp_text_code->rc_data.rc_badcharset = NULL;
146 }
147 break;
148
149 case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
150 if (session->imap_connection_info) {
151 if (session->imap_connection_info->imap_capability != NULL)
152 mailimap_capability_data_free(session->imap_connection_info->imap_capability);
153 session->imap_connection_info->imap_capability =
154 resp_text_code->rc_data.rc_cap_data;
155 /* detach before free */
156 resp_text_code->rc_data.rc_cap_data = NULL;
157 }
158 break;
159
160 case MAILIMAP_RESP_TEXT_CODE_PARSE:
161 if (session->imap_response_info) {
162 if (session->imap_response_info->rsp_parse != NULL)
163 free(session->imap_response_info->rsp_parse);
164 session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text);
165 }
166 break;
167
168 case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
169 if (session->imap_selection_info) {
170 if (session->imap_selection_info->sel_perm_flags != NULL) {
171 clist_foreach(session->imap_selection_info->sel_perm_flags,
172 (clist_func) mailimap_flag_perm_free, NULL);
173 clist_free(session->imap_selection_info->sel_perm_flags);
174 }
175 session->imap_selection_info->sel_perm_flags =
176 resp_text_code->rc_data.rc_perm_flags;
177 /* detach before free */
178 resp_text_code->rc_data.rc_perm_flags = NULL;
179 }
180 break;
181
182 case MAILIMAP_RESP_TEXT_CODE_READ_ONLY:
183 if (session->imap_selection_info)
184 session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY;
185 break;
186
187 case MAILIMAP_RESP_TEXT_CODE_READ_WRITE:
188 if (session->imap_selection_info)
189 session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE;
190 break;
191
192 case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE:
193 if (session->imap_response_info)
194 session->imap_response_info->rsp_trycreate = TRUE;
195 break;
196
197 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
198 if (session->imap_selection_info)
199 session->imap_selection_info->sel_uidnext =
200 resp_text_code->rc_data.rc_uidnext;
201 break;
202
203 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
204 if (session->imap_selection_info)
205 session->imap_selection_info->sel_uidvalidity =
206 resp_text_code->rc_data.rc_uidvalidity;
207 break;
208
209 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
210 if (session->imap_selection_info)
211 session->imap_selection_info->sel_first_unseen =
212 resp_text_code->rc_data.rc_first_unseen;
213 break;
214 }
215 }
216}
217
218static void resp_cond_state_store(mailimap * session,
219 struct mailimap_resp_cond_state * resp_cond_state)
220{
221 resp_text_store(session, resp_cond_state->rsp_text);
222}
223
224static void mailbox_data_store(mailimap * session,
225 struct mailimap_mailbox_data * mb_data)
226{
227 int r;
228
229 switch (mb_data->mbd_type) {
230 case MAILIMAP_MAILBOX_DATA_FLAGS:
231 if (session->imap_selection_info) {
232 if (session->imap_selection_info->sel_flags != NULL)
233 mailimap_flag_list_free(session->imap_selection_info->sel_flags);
234 session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags;
235 mb_data->mbd_data.mbd_flags = NULL;
236 }
237 break;
238
239 case MAILIMAP_MAILBOX_DATA_LIST:
240 if (session->imap_response_info) {
241 r = clist_append(session->imap_response_info->rsp_mailbox_list,
242 mb_data->mbd_data.mbd_list);
243 if (r == 0)
244 mb_data->mbd_data.mbd_list = NULL;
245 else {
246 /* TODO must handle error case */
247 }
248 }
249 break;
250
251 case MAILIMAP_MAILBOX_DATA_LSUB:
252 if (session->imap_response_info) {
253 r = clist_append(session->imap_response_info->rsp_mailbox_lsub,
254 mb_data->mbd_data.mbd_lsub);
255 if (r == 0)
256 mb_data->mbd_data.mbd_lsub = NULL;
257 else {
258 /* TODO must handle error case */
259 }
260 }
261 break;
262
263 case MAILIMAP_MAILBOX_DATA_SEARCH:
264 if (session->imap_response_info) {
265 if (session->imap_response_info->rsp_search_result != NULL) {
266 if (mb_data->mbd_data.mbd_search != NULL) {
267 clist_concat(session->imap_response_info->rsp_search_result,
268 mb_data->mbd_data.mbd_search);
269 clist_free(mb_data->mbd_data.mbd_search);
270 mb_data->mbd_data.mbd_search = NULL;
271 }
272 }
273 else {
274 if (mb_data->mbd_data.mbd_search != NULL) {
275 session->imap_response_info->rsp_search_result =
276 mb_data->mbd_data.mbd_search;
277 mb_data->mbd_data.mbd_search = NULL;
278 }
279 }
280 }
281 break;
282
283 case MAILIMAP_MAILBOX_DATA_STATUS:
284 if (session->imap_response_info) {
285 if (session->imap_response_info->rsp_status != NULL)
286 mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status);
287 session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status;
288#if 0
289 if (session->imap_selection_info != NULL) {
290 clistiter * cur;
291
292 for(cur = clist_begin(mb_data->status->status_info_list)
293 ; cur != NULL ; cur = clist_next(cur)) {
294 struct mailimap_status_info * info;
295
296 info = clist_content(cur);
297 switch (info->att) {
298 case MAILIMAP_STATUS_ATT_MESSAGES:
299 session->imap_selection_info->exists = info->value;
300 break;
301 case MAILIMAP_STATUS_ATT_RECENT:
302 session->imap_selection_info->recent = info->value;
303 break;
304 case MAILIMAP_STATUS_ATT_UIDNEXT:
305 session->imap_selection_info->uidnext = info->value;
306 break;
307 case MAILIMAP_STATUS_ATT_UIDVALIDITY:
308 session->imap_selection_info->uidvalidity = info->value;
309 break;
310 case MAILIMAP_STATUS_ATT_UNSEEN:
311 session->imap_selection_info->unseen = info->value;
312 break;
313 }
314 }
315 }
316#endif
317#if 0
318 mailimap_mailbox_data_status_free(mb_data->status);
319#endif
320 mb_data->mbd_data.mbd_status = NULL;
321 }
322 break;
323
324 case MAILIMAP_MAILBOX_DATA_EXISTS:
325 if (session->imap_selection_info)
326 session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists;
327 break;
328
329 case MAILIMAP_MAILBOX_DATA_RECENT:
330 if (session->imap_selection_info)
331 session->imap_selection_info->sel_recent =
332 mb_data->mbd_data.mbd_recent;
333 break;
334 }
335}
336
337static void
338message_data_store(mailimap * session,
339 struct mailimap_message_data * msg_data)
340{
341 uint32_t * expunged;
342 int r;
343
344 switch (msg_data->mdt_type) {
345 case MAILIMAP_MESSAGE_DATA_EXPUNGE:
346 if (session->imap_response_info) {
347 expunged = mailimap_number_alloc_new(msg_data->mdt_number);
348 if (expunged != NULL) {
349 r = clist_append(session->imap_response_info->rsp_expunged, expunged);
350 if (r == 0) {
351 /* do nothing */
352 }
353 else {
354 /* TODO : must handle error case */
355 mailimap_number_alloc_free(expunged);
356 }
357 if (session->imap_selection_info != NULL)
358 session->imap_selection_info->sel_exists --;
359 }
360 }
361 break;
362
363 case MAILIMAP_MESSAGE_DATA_FETCH:
364 r = clist_append(session->imap_response_info->rsp_fetch_list,
365 msg_data->mdt_msg_att);
366 if (r == 0) {
367 msg_data->mdt_msg_att->att_number = msg_data->mdt_number;
368 msg_data->mdt_msg_att = NULL;
369 }
370 else {
371 /* TODO : must handle error case */
372 }
373 break;
374 }
375}
376
377static void
378cont_req_or_resp_data_store(mailimap * session,
379 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data)
380{
381 if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) {
382 struct mailimap_response_data * resp_data;
383
384 resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data;
385
386 switch (resp_data->rsp_type) {
387 case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
388 resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state);
389 break;
390 case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
391 mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data);
392 break;
393 case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
394 message_data_store(session, resp_data->rsp_data.rsp_message_data);
395 break;
396 case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
397 if (session->imap_connection_info) {
398 if (session->imap_connection_info->imap_capability != NULL)
399 mailimap_capability_data_free(session->imap_connection_info->imap_capability);
400 session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data;
401 resp_data->rsp_data.rsp_capability_data = NULL;
402 }
403 break;
404 }
405 }
406}
407
408static void response_tagged_store(mailimap * session,
409 struct mailimap_response_tagged * tagged)
410{
411 resp_cond_state_store(session, tagged->rsp_cond_state);
412}
413
414static void resp_cond_bye_store(mailimap * session,
415 struct mailimap_resp_cond_bye * resp_cond_bye)
416{
417 resp_text_store(session, resp_cond_bye->rsp_text);
418}
419
420static void response_fatal_store(mailimap * session,
421 struct mailimap_response_fatal * fatal)
422{
423 resp_cond_bye_store(session, fatal->rsp_bye);
424}
425
426static void response_done_store(mailimap * session,
427 struct mailimap_response_done * resp_done)
428{
429 switch(resp_done->rsp_type) {
430 case MAILIMAP_RESP_DONE_TYPE_TAGGED:
431 response_tagged_store(session, resp_done->rsp_data.rsp_tagged);
432 break;
433 case MAILIMAP_RESP_DONE_TYPE_FATAL:
434 response_fatal_store(session, resp_done->rsp_data.rsp_fatal);
435 break;
436 }
437}
438
439static void
440response_store(mailimap * session,
441 struct mailimap_response * response)
442{
443 clistiter * cur;
444
445 if (session->imap_response_info) {
446 mailimap_response_info_free(session->imap_response_info);
447 session->imap_response_info = NULL;
448 }
449
450 session->imap_response_info = mailimap_response_info_new();
451 if (session->imap_response_info == NULL) {
452 /* ignored error */
453 return;
454 }
455
456 if (response->rsp_cont_req_or_resp_data_list != NULL) {
457 for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ;
458 cur != NULL ; cur = clist_next(cur)) {
459 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
460
461 cont_req_or_resp_data = clist_content(cur);
462
463 cont_req_or_resp_data_store(session, cont_req_or_resp_data);
464 }
465 }
466
467 response_done_store(session, response->rsp_resp_done);
468}
469
470static void resp_cond_auth_store(mailimap * session,
471 struct mailimap_resp_cond_auth * cond_auth)
472{
473 resp_text_store(session, cond_auth->rsp_text);
474}
475
476static void greeting_store(mailimap * session,
477 struct mailimap_greeting * greeting)
478{
479 switch (greeting->gr_type) {
480 case MAILIMAP_GREETING_RESP_COND_AUTH:
481 resp_cond_auth_store(session, greeting->gr_data.gr_auth);
482 break;
483
484 case MAILIMAP_GREETING_RESP_COND_BYE:
485 resp_cond_bye_store(session, greeting->gr_data.gr_bye);
486 break;
487 }
488}
489
490int mailimap_connect(mailimap * session, mailstream * s)
491{
492 struct mailimap_greeting * greeting;
493 int r;
494 int auth_type;
495 struct mailimap_connection_info * connection_info;
496
497 if (session->imap_state != MAILIMAP_STATE_DISCONNECTED)
498 return MAILIMAP_ERROR_BAD_STATE;
499
500 session->imap_stream = s;
501
502 if (session->imap_connection_info)
503 mailimap_connection_info_free(session->imap_connection_info);
504 connection_info = mailimap_connection_info_new();
505 if (connection_info != NULL)
506 session->imap_connection_info = connection_info;
507
508 if (read_line(session) == NULL) {
509 return MAILIMAP_ERROR_STREAM;
510 }
511
512 r = parse_greeting(session, &greeting);
513 if (r != MAILIMAP_NO_ERROR) {
514 return r;
515 }
516
517 auth_type = greeting->gr_data.gr_auth->rsp_type;
518
519 mailimap_greeting_free(greeting);
520
521 switch (auth_type) {
522 case MAILIMAP_RESP_COND_AUTH_PREAUTH:
523 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
524 return MAILIMAP_NO_ERROR_AUTHENTICATED;
525 default:
526 session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED;
527 return MAILIMAP_NO_ERROR_NON_AUTHENTICATED;
528 }
529}
530
531
532
533
534
535
536
537
538/* ********************************************************************** */
539
540
541
542int mailimap_append(mailimap * session, const char * mailbox,
543 struct mailimap_flag_list * flag_list,
544 struct mailimap_date_time * date_time,
545 const char * literal, size_t literal_size)
546{
547 struct mailimap_response * response;
548 int r;
549 int error_code;
550 struct mailimap_continue_req * cont_req;
551 size_t index;
552 size_t fixed_literal_size;
553
554 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
555 (session->imap_state != MAILIMAP_STATE_SELECTED))
556 return MAILIMAP_ERROR_BAD_STATE;
557
558 r = send_current_tag(session);
559 if (r != MAILIMAP_NO_ERROR)
560 return r;
561
562 fixed_literal_size = mailstream_get_data_crlf_size(literal, literal_size);
563
564 r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time,
565 fixed_literal_size);
566 if (r != MAILIMAP_NO_ERROR)
567 return r;
568
569 if (mailstream_flush(session->imap_stream) == -1)
570 return MAILIMAP_ERROR_STREAM;
571
572 if (read_line(session) == NULL)
573 return MAILIMAP_ERROR_STREAM;
574
575 index = 0;
576
577 r = mailimap_continue_req_parse(session->imap_stream,
578 session->imap_stream_buffer,
579 &index, &cont_req,
580 session->imap_progr_rate, session->imap_progr_fun);
581 if (r == MAILIMAP_NO_ERROR)
582 mailimap_continue_req_free(cont_req);
583
584 if (r == MAILIMAP_ERROR_PARSE) {
585 r = parse_response(session, &response);
586 if (r != MAILIMAP_NO_ERROR)
587 return r;
588 mailimap_response_free(response);
589
590 return MAILIMAP_ERROR_APPEND;
591 }
592
593 r = mailimap_literal_data_send(session->imap_stream, literal, literal_size,
594 session->imap_progr_rate, session->imap_progr_fun);
595 if (r != MAILIMAP_NO_ERROR)
596 return r;
597
598 r = mailimap_crlf_send(session->imap_stream);
599 if (r != MAILIMAP_NO_ERROR)
600 return r;
601
602 if (mailstream_flush(session->imap_stream) == -1)
603 return MAILIMAP_ERROR_STREAM;
604
605 if (read_line(session) == NULL)
606 return MAILIMAP_ERROR_STREAM;
607
608 r = parse_response(session, &response);
609 if (r != MAILIMAP_NO_ERROR)
610 return r;
611
612 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
613
614 mailimap_response_free(response);
615
616 switch (error_code) {
617 case MAILIMAP_RESP_COND_STATE_OK:
618 return MAILIMAP_NO_ERROR;
619
620 default:
621 return MAILIMAP_ERROR_APPEND;
622 }
623}
624
625/*
626gboolean mailimap_authenticate(mailimap * session,
627 gchar * auth_type)
628{
629}
630
631gboolean mailimap_authenticate_resp_send(mailimap * session,
632 gchar * base64)
633{
634}
635*/
636
637int mailimap_noop(mailimap * session)
638{
639 struct mailimap_response * response;
640 int r;
641 int error_code;
642
643 r = send_current_tag(session);
644 if (r != MAILIMAP_NO_ERROR)
645 return r;
646
647 r = mailimap_noop_send(session->imap_stream);
648 if (r != MAILIMAP_NO_ERROR)
649 return r;
650
651 r = mailimap_crlf_send(session->imap_stream);
652 if (r != MAILIMAP_NO_ERROR)
653 return r;
654
655 if (mailstream_flush(session->imap_stream) == -1)
656 return MAILIMAP_ERROR_STREAM;
657
658 if (read_line(session) == NULL)
659 return MAILIMAP_ERROR_STREAM;
660
661 r = parse_response(session, &response);
662 if (r != MAILIMAP_NO_ERROR)
663 return r;
664
665 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
666
667 mailimap_response_free(response);
668
669 switch (error_code) {
670 case MAILIMAP_RESP_COND_STATE_OK:
671 return MAILIMAP_NO_ERROR;
672
673 default:
674 return MAILIMAP_ERROR_NOOP;
675 }
676}
677
678int mailimap_logout(mailimap * session)
679{
680 struct mailimap_response * response;
681 int r;
682 int error_code;
683 int res;
684
685 r = send_current_tag(session);
686 if (r != MAILIMAP_NO_ERROR) {
687 res = r;
688 goto close;
689 }
690
691 r = mailimap_logout_send(session->imap_stream);
692 if (r != MAILIMAP_NO_ERROR) {
693 res = r;
694 goto close;
695 }
696
697 r = mailimap_crlf_send(session->imap_stream);
698 if (r != MAILIMAP_NO_ERROR) {
699 res = r;
700 goto close;
701 }
702
703 if (mailstream_flush(session->imap_stream) == -1) {
704 res = MAILIMAP_ERROR_STREAM;
705 goto close;
706 }
707
708 if (read_line(session) == NULL) {
709 res = MAILIMAP_ERROR_STREAM;
710 goto close;
711 }
712
713 r = parse_response(session, &response);
714 if (r != MAILIMAP_NO_ERROR) {
715 res = r;
716 goto close;
717 }
718
719 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
720
721 mailimap_response_free(response);
722
723 switch (error_code) {
724 case MAILIMAP_RESP_COND_STATE_OK:
725 if (session->imap_connection_info) {
726 mailimap_connection_info_free(session->imap_connection_info);
727 session->imap_connection_info = NULL;
728 }
729 res = MAILIMAP_NO_ERROR;
730 goto close;
731
732 default:
733 res = MAILIMAP_ERROR_LOGOUT;
734 goto close;
735 }
736
737 close:
738 mailstream_close(session->imap_stream);
739 session->imap_stream = NULL;
740 session->imap_state = MAILIMAP_STATE_DISCONNECTED;
741 return res;
742}
743
744/* send the results back to the caller */
745/* duplicate the result */
746
747static struct mailimap_capability *
748mailimap_capability_dup(struct mailimap_capability * orig_cap)
749{
750 struct mailimap_capability * cap;
751 char * auth_type;
752 char * name;
753
754 name = NULL;
755 auth_type = NULL;
756 switch (orig_cap->cap_type) {
757 case MAILIMAP_CAPABILITY_NAME:
758 name = strdup(orig_cap->cap_data.cap_name);
759 if (name == NULL)
760 goto err;
761 break;
762 case MAILIMAP_CAPABILITY_AUTH_TYPE:
763 auth_type = strdup(orig_cap->cap_data.cap_auth_type);
764 if (auth_type == NULL)
765 goto err;
766 break;
767 }
768
769 cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name);
770 if (cap == NULL)
771 goto free;
772
773 return cap;
774
775 free:
776 if (name != NULL)
777 free(name);
778 if (auth_type != NULL)
779 free(auth_type);
780 err:
781 return NULL;
782}
783
784static struct mailimap_capability_data *
785mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data)
786{
787 struct mailimap_capability_data * cap_data;
788 struct mailimap_capability * cap_dup;
789 clist * list;
790 clistiter * cur;
791 int r;
792
793 list = clist_new();
794 if (list == NULL)
795 goto err;
796
797 for(cur = clist_begin(orig_cap_data->cap_list) ;
798 cur != NULL ; cur = clist_next(cur)) {
799 struct mailimap_capability * cap;
800
801 cap = clist_content(cur);
802
803 cap_dup = mailimap_capability_dup(cap);
804 if (cap_dup == NULL)
805 goto list;
806
807 r = clist_append(list, cap_dup);
808 if (r < 0) {
809 mailimap_capability_free(cap_dup);
810 goto list;
811 }
812 }
813
814 cap_data = mailimap_capability_data_new(list);
815 if (cap_data == NULL)
816 goto list;
817
818 return cap_data;
819
820list:
821 clist_foreach(list, (clist_func) mailimap_capability_free, NULL);
822 clist_free(list);
823err:
824 return NULL;
825}
826
827int mailimap_capability(mailimap * session,
828 struct mailimap_capability_data ** result)
829{
830 struct mailimap_response * response;
831 int r;
832 int error_code;
833 struct mailimap_capability_data * cap_data;
834
835 r = send_current_tag(session);
836 if (r != MAILIMAP_NO_ERROR)
837 return r;
838
839 r = mailimap_capability_send(session->imap_stream);
840 if (r != MAILIMAP_NO_ERROR)
841 return r;
842
843 r = mailimap_crlf_send(session->imap_stream);
844 if (r != MAILIMAP_NO_ERROR)
845 return r;
846
847 if (mailstream_flush(session->imap_stream) == -1)
848 return MAILIMAP_ERROR_STREAM;
849
850 if (read_line(session) == NULL)
851 return MAILIMAP_ERROR_STREAM;
852
853 r = parse_response(session, &response);
854 if (r != MAILIMAP_NO_ERROR)
855 return r;
856
857 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
858
859 mailimap_response_free(response);
860
861 switch (error_code) {
862 case MAILIMAP_RESP_COND_STATE_OK:
863 cap_data =
864 mailimap_capability_data_dup(session->imap_connection_info->imap_capability);
865 if (cap_data == NULL)
866 return MAILIMAP_ERROR_MEMORY;
867
868 * result = cap_data;
869
870 return MAILIMAP_NO_ERROR;
871
872 default:
873 return MAILIMAP_ERROR_CAPABILITY;
874 }
875}
876
877int mailimap_check(mailimap * session)
878{
879 struct mailimap_response * response;
880 int r;
881 int error_code;
882
883 if (session->imap_state != MAILIMAP_STATE_SELECTED)
884 return MAILIMAP_ERROR_BAD_STATE;
885
886 r = send_current_tag(session);
887 if (r != MAILIMAP_NO_ERROR)
888 return r;
889
890 r = mailimap_check_send(session->imap_stream);
891 if (r != MAILIMAP_NO_ERROR)
892 return r;
893
894 r = mailimap_crlf_send(session->imap_stream);
895 if (r != MAILIMAP_NO_ERROR)
896 return r;
897
898 if (mailstream_flush(session->imap_stream) == -1)
899 return MAILIMAP_ERROR_STREAM;
900
901 if (read_line(session) == NULL)
902 return MAILIMAP_ERROR_STREAM;
903
904 r = parse_response(session, &response);
905 if (r != MAILIMAP_NO_ERROR)
906 return r;
907
908 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
909
910 mailimap_response_free(response);
911
912 switch (error_code) {
913 case MAILIMAP_RESP_COND_STATE_OK:
914 return MAILIMAP_NO_ERROR;
915
916 default:
917 return MAILIMAP_ERROR_CHECK;
918 }
919}
920
921int mailimap_close(mailimap * session)
922{
923 struct mailimap_response * response;
924 int r;
925 int error_code;
926
927 if (session->imap_state != MAILIMAP_STATE_SELECTED)
928 return MAILIMAP_ERROR_BAD_STATE;
929
930 r = send_current_tag(session);
931 if (r != MAILIMAP_NO_ERROR)
932 return r;
933
934 r = mailimap_close_send(session->imap_stream);
935 if (r != MAILIMAP_NO_ERROR)
936 return r;
937
938 r = mailimap_crlf_send(session->imap_stream);
939 if (r != MAILIMAP_NO_ERROR)
940 return r;
941
942 if (mailstream_flush(session->imap_stream) == -1)
943 return MAILIMAP_ERROR_STREAM;
944
945 if (read_line(session) == NULL)
946 return MAILIMAP_ERROR_STREAM;
947
948 r = parse_response(session, &response);
949 if (r != MAILIMAP_NO_ERROR)
950 return r;
951
952 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
953
954 mailimap_response_free(response);
955
956 switch (error_code) {
957 case MAILIMAP_RESP_COND_STATE_OK:
958 /* leave selected state */
959 mailimap_selection_info_free(session->imap_selection_info);
960 session->imap_selection_info = NULL;
961
962 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
963 return MAILIMAP_NO_ERROR;
964
965 default:
966 return MAILIMAP_ERROR_CLOSE;
967 }
968}
969
970int mailimap_expunge(mailimap * session)
971{
972 struct mailimap_response * response;
973 int r;
974 int error_code;
975
976 if (session->imap_state != MAILIMAP_STATE_SELECTED)
977 return MAILIMAP_ERROR_BAD_STATE;
978
979 r = send_current_tag(session);
980 if (r != MAILIMAP_NO_ERROR)
981 return r;
982
983 r = mailimap_expunge_send(session->imap_stream);
984 if (r != MAILIMAP_NO_ERROR)
985 return r;
986
987 r = mailimap_crlf_send(session->imap_stream);
988 if (r != MAILIMAP_NO_ERROR)
989 return r;
990
991 if (mailstream_flush(session->imap_stream) == -1)
992 return MAILIMAP_ERROR_STREAM;
993
994 if (read_line(session) == NULL)
995 return MAILIMAP_ERROR_STREAM;
996
997 r = parse_response(session, &response);
998 if (r != MAILIMAP_NO_ERROR)
999 return r;
1000
1001 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1002
1003 mailimap_response_free(response);
1004
1005 switch (error_code) {
1006 case MAILIMAP_RESP_COND_STATE_OK:
1007 return MAILIMAP_NO_ERROR;
1008
1009 default:
1010 return MAILIMAP_ERROR_EXPUNGE;
1011 }
1012}
1013
1014int mailimap_copy(mailimap * session, struct mailimap_set * set,
1015 const char * mb)
1016{
1017 struct mailimap_response * response;
1018 int r;
1019 int error_code;
1020
1021 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1022 return MAILIMAP_ERROR_BAD_STATE;
1023
1024 r = send_current_tag(session);
1025 if (r != MAILIMAP_NO_ERROR)
1026 return r;
1027
1028 r = mailimap_copy_send(session->imap_stream, set, mb);
1029 if (r != MAILIMAP_NO_ERROR)
1030 return r;
1031
1032 r = mailimap_crlf_send(session->imap_stream);
1033 if (r != MAILIMAP_NO_ERROR)
1034 return r;
1035
1036 if (mailstream_flush(session->imap_stream) == -1)
1037 return MAILIMAP_ERROR_STREAM;
1038
1039 if (read_line(session) == NULL)
1040 return MAILIMAP_ERROR_STREAM;
1041
1042 r = parse_response(session, &response);
1043 if (r != MAILIMAP_NO_ERROR)
1044 return r;
1045
1046 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1047
1048 mailimap_response_free(response);
1049
1050 switch (error_code) {
1051 case MAILIMAP_RESP_COND_STATE_OK:
1052 return MAILIMAP_NO_ERROR;
1053
1054 default:
1055 return MAILIMAP_ERROR_COPY;
1056 }
1057}
1058
1059int mailimap_uid_copy(mailimap * session, struct mailimap_set * set,
1060 const char * mb)
1061{
1062 struct mailimap_response * response;
1063 int r;
1064 int error_code;
1065
1066 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1067 return MAILIMAP_ERROR_BAD_STATE;
1068
1069 r = send_current_tag(session);
1070 if (r != MAILIMAP_NO_ERROR)
1071 return r;
1072
1073 r = mailimap_uid_copy_send(session->imap_stream, set, mb);
1074 if (r != MAILIMAP_NO_ERROR)
1075 return r;
1076
1077 r = mailimap_crlf_send(session->imap_stream);
1078 if (r != MAILIMAP_NO_ERROR)
1079 return r;
1080
1081 if (mailstream_flush(session->imap_stream) == -1)
1082 return MAILIMAP_ERROR_STREAM;
1083
1084 if (read_line(session) == NULL)
1085 return MAILIMAP_ERROR_STREAM;
1086
1087 r = parse_response(session, &response);
1088 if (r != MAILIMAP_NO_ERROR)
1089 return r;
1090
1091 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1092
1093 mailimap_response_free(response);
1094
1095 switch (error_code) {
1096 case MAILIMAP_RESP_COND_STATE_OK:
1097 return MAILIMAP_NO_ERROR;
1098
1099 default:
1100 return MAILIMAP_ERROR_UID_COPY;
1101 }
1102}
1103
1104int mailimap_create(mailimap * session, const char * mb)
1105{
1106 struct mailimap_response * response;
1107 int r;
1108 int error_code;
1109
1110 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1111 (session->imap_state != MAILIMAP_STATE_SELECTED))
1112 return MAILIMAP_ERROR_BAD_STATE;
1113
1114 r = send_current_tag(session);
1115 if (r != MAILIMAP_NO_ERROR)
1116 return r;
1117
1118 r = mailimap_create_send(session->imap_stream, mb);
1119 if (r != MAILIMAP_NO_ERROR)
1120 return r;
1121
1122 r = mailimap_crlf_send(session->imap_stream);
1123 if (r != MAILIMAP_NO_ERROR)
1124 return r;
1125
1126 if (mailstream_flush(session->imap_stream) == -1)
1127 return MAILIMAP_ERROR_STREAM;
1128
1129 if (read_line(session) == NULL)
1130 return MAILIMAP_ERROR_STREAM;
1131
1132 r = parse_response(session, &response);
1133 if (r != MAILIMAP_NO_ERROR)
1134 return r;
1135
1136 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1137
1138 mailimap_response_free(response);
1139
1140 switch (error_code) {
1141 case MAILIMAP_RESP_COND_STATE_OK:
1142 return MAILIMAP_NO_ERROR;
1143
1144 default:
1145 return MAILIMAP_ERROR_CREATE;
1146 }
1147}
1148
1149
1150int mailimap_delete(mailimap * session, const char * mb)
1151{
1152 struct mailimap_response * response;
1153 int r;
1154 int error_code;
1155
1156 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1157 (session->imap_state != MAILIMAP_STATE_SELECTED))
1158 return MAILIMAP_ERROR_BAD_STATE;
1159
1160 r = send_current_tag(session);
1161 if (r != MAILIMAP_NO_ERROR)
1162 return r;
1163
1164 r = mailimap_delete_send(session->imap_stream, mb);
1165 if (r != MAILIMAP_NO_ERROR)
1166 return r;
1167
1168 r = mailimap_crlf_send(session->imap_stream);
1169 if (r != MAILIMAP_NO_ERROR)
1170 return r;
1171
1172 if (mailstream_flush(session->imap_stream) == -1)
1173 return MAILIMAP_ERROR_STREAM;
1174
1175 if (read_line(session) == NULL)
1176 return MAILIMAP_ERROR_STREAM;
1177
1178 r = parse_response(session, &response);
1179 if (r != MAILIMAP_NO_ERROR)
1180 return r;
1181
1182 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1183
1184 mailimap_response_free(response);
1185
1186 switch (error_code) {
1187 case MAILIMAP_RESP_COND_STATE_OK:
1188 return MAILIMAP_NO_ERROR;
1189
1190 default:
1191 return MAILIMAP_ERROR_DELETE;
1192 }
1193}
1194
1195int mailimap_examine(mailimap * session, const char * mb)
1196{
1197 struct mailimap_response * response;
1198 int r;
1199 int error_code;
1200
1201 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1202 (session->imap_state != MAILIMAP_STATE_SELECTED))
1203 return MAILIMAP_ERROR_BAD_STATE;
1204
1205 r = send_current_tag(session);
1206 if (r != MAILIMAP_NO_ERROR)
1207 return r;
1208
1209 r = mailimap_examine_send(session->imap_stream, mb);
1210 if (r != MAILIMAP_NO_ERROR)
1211 return r;
1212
1213 r = mailimap_crlf_send(session->imap_stream);
1214 if (r != MAILIMAP_NO_ERROR)
1215 return r;
1216
1217 if (mailstream_flush(session->imap_stream) == -1)
1218 return MAILIMAP_ERROR_STREAM;
1219
1220 if (read_line(session) == NULL)
1221 return MAILIMAP_ERROR_STREAM;
1222
1223 if (session->imap_selection_info != NULL)
1224 mailimap_selection_info_free(session->imap_selection_info);
1225 session->imap_selection_info = mailimap_selection_info_new();
1226
1227 r = parse_response(session, &response);
1228 if (r != MAILIMAP_NO_ERROR)
1229 return r;
1230
1231 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1232
1233 mailimap_response_free(response);
1234
1235 switch (error_code) {
1236 case MAILIMAP_RESP_COND_STATE_OK:
1237 session->imap_state = MAILIMAP_STATE_SELECTED;
1238 return MAILIMAP_NO_ERROR;
1239
1240 default:
1241 mailimap_selection_info_free(session->imap_selection_info);
1242 session->imap_selection_info = NULL;
1243 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1244 return MAILIMAP_ERROR_EXAMINE;
1245 }
1246}
1247
1248int
1249mailimap_fetch(mailimap * session, struct mailimap_set * set,
1250 struct mailimap_fetch_type * fetch_type, clist ** result)
1251{
1252 struct mailimap_response * response;
1253 int r;
1254 int error_code;
1255
1256 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1257 return MAILIMAP_ERROR_BAD_STATE;
1258
1259 r = send_current_tag(session);
1260 if (r != MAILIMAP_NO_ERROR)
1261 return r;
1262
1263 r = mailimap_fetch_send(session->imap_stream, set, fetch_type);
1264 if (r != MAILIMAP_NO_ERROR)
1265 return r;
1266
1267 r = mailimap_crlf_send(session->imap_stream);
1268 if (r != MAILIMAP_NO_ERROR)
1269 return r;
1270
1271 if (mailstream_flush(session->imap_stream) == -1)
1272 return MAILIMAP_ERROR_STREAM;
1273
1274 if (read_line(session) == NULL)
1275 return MAILIMAP_ERROR_STREAM;
1276
1277 r = parse_response(session, &response);
1278 if (r != MAILIMAP_NO_ERROR)
1279 return r;
1280
1281 * result = session->imap_response_info->rsp_fetch_list;
1282 session->imap_response_info->rsp_fetch_list = NULL;
1283
1284 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1285
1286 mailimap_response_free(response);
1287
1288 switch (error_code) {
1289 case MAILIMAP_RESP_COND_STATE_OK:
1290 return MAILIMAP_NO_ERROR;
1291
1292 default:
1293 return MAILIMAP_ERROR_FETCH;
1294 }
1295}
1296
1297void mailimap_fetch_list_free(clist * fetch_list)
1298{
1299 clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL);
1300 clist_free(fetch_list);
1301}
1302
1303int
1304mailimap_uid_fetch(mailimap * session,
1305 struct mailimap_set * set,
1306 struct mailimap_fetch_type * fetch_type, clist ** result)
1307{
1308 struct mailimap_response * response;
1309 int r;
1310 int error_code;
1311
1312 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1313 return MAILIMAP_ERROR_BAD_STATE;
1314
1315 r = send_current_tag(session);
1316 if (r != MAILIMAP_NO_ERROR)
1317 return r;
1318
1319 r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type);
1320 if (r != MAILIMAP_NO_ERROR)
1321 return r;
1322
1323 r = mailimap_crlf_send(session->imap_stream);
1324 if (r != MAILIMAP_NO_ERROR)
1325 return r;
1326
1327 if (mailstream_flush(session->imap_stream) == -1)
1328 return MAILIMAP_ERROR_STREAM;
1329
1330 if (read_line(session) == NULL)
1331 return MAILIMAP_ERROR_STREAM;
1332
1333 r = parse_response(session, &response);
1334
1335 if (r != MAILIMAP_NO_ERROR)
1336 return r;
1337
1338 * result = session->imap_response_info->rsp_fetch_list;
1339 session->imap_response_info->rsp_fetch_list = NULL;
1340
1341 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1342
1343 mailimap_response_free(response);
1344
1345 switch (error_code) {
1346 case MAILIMAP_RESP_COND_STATE_OK:
1347 return MAILIMAP_NO_ERROR;
1348
1349 default:
1350 return MAILIMAP_ERROR_UID_FETCH;
1351 }
1352}
1353
1354int mailimap_list(mailimap * session, const char * mb,
1355 const char * list_mb, clist ** result)
1356{
1357 struct mailimap_response * response;
1358 int r;
1359 int error_code;
1360
1361 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1362 (session->imap_state != MAILIMAP_STATE_SELECTED))
1363 return MAILIMAP_ERROR_BAD_STATE;
1364
1365 r = send_current_tag(session);
1366 if (r != MAILIMAP_NO_ERROR)
1367 return r;
1368
1369 r = mailimap_list_send(session->imap_stream, mb, list_mb);
1370 if (r != MAILIMAP_NO_ERROR)
1371 return r;
1372
1373 r = mailimap_crlf_send(session->imap_stream);
1374 if (r != MAILIMAP_NO_ERROR)
1375 return r;
1376
1377 if (mailstream_flush(session->imap_stream) == -1)
1378 return MAILIMAP_ERROR_STREAM;
1379
1380 if (read_line(session) == NULL)
1381 return MAILIMAP_ERROR_STREAM;
1382
1383 r = parse_response(session, &response);
1384 if (r != MAILIMAP_NO_ERROR)
1385 return r;
1386
1387 * result = session->imap_response_info->rsp_mailbox_list;
1388 session->imap_response_info->rsp_mailbox_list = NULL;
1389
1390 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1391
1392 mailimap_response_free(response);
1393
1394 switch (error_code) {
1395 case MAILIMAP_RESP_COND_STATE_OK:
1396 return MAILIMAP_NO_ERROR;
1397
1398 default:
1399 return MAILIMAP_ERROR_LIST;
1400 }
1401}
1402
1403int mailimap_login(mailimap * session,
1404 const char * userid, const char * password)
1405{
1406 struct mailimap_response * response;
1407 int r;
1408 int error_code;
1409
1410 if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
1411 return MAILIMAP_ERROR_BAD_STATE;
1412
1413 r = send_current_tag(session);
1414 if (r != MAILIMAP_NO_ERROR)
1415 return r;
1416
1417 r = mailimap_login_send(session->imap_stream, userid, password);
1418 if (r != MAILIMAP_NO_ERROR)
1419 return r;
1420
1421 r = mailimap_crlf_send(session->imap_stream);
1422 if (r != MAILIMAP_NO_ERROR)
1423 return r;
1424
1425 if (mailstream_flush(session->imap_stream) == -1)
1426 return MAILIMAP_ERROR_STREAM;
1427
1428 if (read_line(session) == NULL)
1429 return MAILIMAP_ERROR_STREAM;
1430
1431 r = parse_response(session, &response);
1432 if (r != MAILIMAP_NO_ERROR)
1433 return r;
1434
1435 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1436
1437 mailimap_response_free(response);
1438
1439 switch (error_code) {
1440 case MAILIMAP_RESP_COND_STATE_OK:
1441 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1442 return MAILIMAP_NO_ERROR;
1443
1444 default:
1445 return MAILIMAP_ERROR_LOGIN;
1446 }
1447}
1448
1449int mailimap_lsub(mailimap * session, const char * mb,
1450 const char * list_mb, clist ** result)
1451{
1452 struct mailimap_response * response;
1453 int r;
1454 int error_code;
1455
1456 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1457 (session->imap_state != MAILIMAP_STATE_SELECTED))
1458 return MAILIMAP_ERROR_BAD_STATE;
1459
1460 r = send_current_tag(session);
1461 if (r != MAILIMAP_NO_ERROR)
1462 return r;
1463
1464 r = mailimap_lsub_send(session->imap_stream, mb, list_mb);
1465 if (r != MAILIMAP_NO_ERROR)
1466 return r;
1467
1468 r = mailimap_crlf_send(session->imap_stream);
1469 if (r != MAILIMAP_NO_ERROR)
1470 return r;
1471
1472 if (mailstream_flush(session->imap_stream) == -1)
1473 return MAILIMAP_ERROR_STREAM;
1474
1475 if (read_line(session) == NULL)
1476 return MAILIMAP_ERROR_STREAM;
1477
1478 r = parse_response(session, &response);
1479 if (r != MAILIMAP_NO_ERROR)
1480 return r;
1481
1482 * result = session->imap_response_info->rsp_mailbox_lsub;
1483 session->imap_response_info->rsp_mailbox_lsub = NULL;
1484
1485 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1486
1487 mailimap_response_free(response);
1488
1489 switch (error_code) {
1490 case MAILIMAP_RESP_COND_STATE_OK:
1491 return MAILIMAP_NO_ERROR;
1492
1493 default:
1494 return MAILIMAP_ERROR_LSUB;
1495 }
1496}
1497
1498void mailimap_list_result_free(clist * list)
1499{
1500 clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL);
1501 clist_free(list);
1502}
1503
1504int mailimap_rename(mailimap * session,
1505 const char * mb, const char * new_name)
1506{
1507 struct mailimap_response * response;
1508 int r;
1509 int error_code;
1510
1511 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1512 (session->imap_state != MAILIMAP_STATE_SELECTED))
1513 return MAILIMAP_ERROR_BAD_STATE;
1514
1515 r = send_current_tag(session);
1516 if (r != MAILIMAP_NO_ERROR)
1517 return r;
1518
1519 r = mailimap_rename_send(session->imap_stream, mb, new_name);
1520 if (r != MAILIMAP_NO_ERROR)
1521 return r;
1522
1523 if (!mailimap_crlf_send(session->imap_stream))
1524 if (r != MAILIMAP_NO_ERROR)
1525 return r;
1526
1527 if (mailstream_flush(session->imap_stream) == -1)
1528 return MAILIMAP_ERROR_STREAM;
1529
1530 if (read_line(session) == NULL)
1531 return MAILIMAP_ERROR_STREAM;
1532
1533 r = parse_response(session, &response);
1534 if (r != MAILIMAP_NO_ERROR)
1535 return r;
1536
1537 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1538
1539 mailimap_response_free(response);
1540
1541 switch (error_code) {
1542 case MAILIMAP_RESP_COND_STATE_OK:
1543 return MAILIMAP_NO_ERROR;
1544
1545 default:
1546 return MAILIMAP_ERROR_RENAME;
1547 }
1548}
1549
1550int
1551mailimap_search(mailimap * session, const char * charset,
1552 struct mailimap_search_key * key, clist ** result)
1553{
1554 struct mailimap_response * response;
1555 int r;
1556 int error_code;
1557
1558 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1559 return MAILIMAP_ERROR_BAD_STATE;
1560
1561 r = send_current_tag(session);
1562 if (r != MAILIMAP_NO_ERROR)
1563 return r;
1564
1565 r = mailimap_search_send(session->imap_stream, charset, key);
1566 if (r != MAILIMAP_NO_ERROR)
1567 return r;
1568
1569 r = mailimap_crlf_send(session->imap_stream);
1570 if (r != MAILIMAP_NO_ERROR)
1571 return r;
1572
1573 if (mailstream_flush(session->imap_stream) == -1)
1574 return MAILIMAP_ERROR_STREAM;
1575
1576 if (read_line(session) == NULL)
1577 return MAILIMAP_ERROR_STREAM;
1578
1579 r = parse_response(session, &response);
1580 if (r != MAILIMAP_NO_ERROR)
1581 return r;
1582
1583 * result = session->imap_response_info->rsp_search_result;
1584 session->imap_response_info->rsp_search_result = NULL;
1585
1586 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1587
1588 mailimap_response_free(response);
1589
1590 switch (error_code) {
1591 case MAILIMAP_RESP_COND_STATE_OK:
1592 return MAILIMAP_NO_ERROR;
1593
1594 default:
1595 return MAILIMAP_ERROR_SEARCH;
1596 }
1597}
1598
1599int
1600mailimap_uid_search(mailimap * session, const char * charset,
1601 struct mailimap_search_key * key, clist ** result)
1602{
1603 struct mailimap_response * response;
1604 int r;
1605 int error_code;
1606
1607 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1608 return MAILIMAP_ERROR_BAD_STATE;
1609
1610 r = send_current_tag(session);
1611 if (r != MAILIMAP_NO_ERROR)
1612 return r;
1613
1614 r = mailimap_uid_search_send(session->imap_stream, charset, key);
1615 if (r != MAILIMAP_NO_ERROR)
1616 return r;
1617
1618 r = mailimap_crlf_send(session->imap_stream);
1619 if (r != MAILIMAP_NO_ERROR)
1620 return r;
1621
1622 if (mailstream_flush(session->imap_stream) == -1)
1623 return MAILIMAP_ERROR_STREAM;
1624
1625 if (read_line(session) == NULL)
1626 return MAILIMAP_ERROR_STREAM;
1627
1628 r = parse_response(session, &response);
1629 if (r != MAILIMAP_NO_ERROR)
1630 return r;
1631
1632 * result = session->imap_response_info->rsp_search_result;
1633 session->imap_response_info->rsp_search_result = NULL;
1634
1635 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1636
1637 mailimap_response_free(response);
1638
1639 switch (error_code) {
1640 case MAILIMAP_RESP_COND_STATE_OK:
1641 return MAILIMAP_NO_ERROR;
1642
1643 default:
1644 return MAILIMAP_ERROR_UID_SEARCH;
1645 }
1646}
1647
1648void mailimap_search_result_free(clist * search_result)
1649{
1650 clist_foreach(search_result, (clist_func) free, NULL);
1651 clist_free(search_result);
1652}
1653
1654int
1655mailimap_select(mailimap * session, const char * mb)
1656{
1657 struct mailimap_response * response;
1658 int r;
1659 int error_code;
1660
1661 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1662 (session->imap_state != MAILIMAP_STATE_SELECTED))
1663 return MAILIMAP_ERROR_BAD_STATE;
1664
1665 r = send_current_tag(session);
1666 if (r != MAILIMAP_NO_ERROR)
1667 return r;
1668
1669 r = mailimap_select_send(session->imap_stream, mb);
1670 if (r != MAILIMAP_NO_ERROR)
1671 return r;
1672
1673 r = mailimap_crlf_send(session->imap_stream);
1674 if (r != MAILIMAP_NO_ERROR)
1675 return r;
1676
1677 if (mailstream_flush(session->imap_stream) == -1)
1678 return MAILIMAP_ERROR_STREAM;
1679
1680 if (read_line(session) == NULL)
1681 return MAILIMAP_ERROR_STREAM;
1682
1683 if (session->imap_selection_info != NULL)
1684 mailimap_selection_info_free(session->imap_selection_info);
1685 session->imap_selection_info = mailimap_selection_info_new();
1686
1687 r = parse_response(session, &response);
1688 if (r != MAILIMAP_NO_ERROR)
1689 return r;
1690
1691 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1692
1693 mailimap_response_free(response);
1694
1695 switch (error_code) {
1696 case MAILIMAP_RESP_COND_STATE_OK:
1697 session->imap_state = MAILIMAP_STATE_SELECTED;
1698 return MAILIMAP_NO_ERROR;
1699
1700 default:
1701 mailimap_selection_info_free(session->imap_selection_info);
1702 session->imap_selection_info = NULL;
1703 session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
1704 return MAILIMAP_ERROR_SELECT;
1705 }
1706}
1707
1708int
1709mailimap_status(mailimap * session, const char * mb,
1710 struct mailimap_status_att_list * status_att_list,
1711 struct mailimap_mailbox_data_status ** result)
1712{
1713 struct mailimap_response * response;
1714 int r;
1715 int error_code;
1716
1717 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1718 (session->imap_state != MAILIMAP_STATE_SELECTED))
1719 return MAILIMAP_ERROR_BAD_STATE;
1720
1721 r = send_current_tag(session);
1722 if (r != MAILIMAP_NO_ERROR)
1723 return r;
1724
1725 r = mailimap_status_send(session->imap_stream, mb, status_att_list);
1726 if (r != MAILIMAP_NO_ERROR)
1727 return r;
1728
1729 r = mailimap_crlf_send(session->imap_stream);
1730 if (r != MAILIMAP_NO_ERROR)
1731 return r;
1732
1733 if (mailstream_flush(session->imap_stream) == -1)
1734 return MAILIMAP_ERROR_STREAM;
1735
1736 if (read_line(session) == NULL)
1737 return MAILIMAP_ERROR_STREAM;
1738
1739 r = parse_response(session, &response);
1740 if (r != MAILIMAP_NO_ERROR)
1741 return r;
1742
1743 * result = session->imap_response_info->rsp_status;
1744 session->imap_response_info->rsp_status = NULL;
1745
1746 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1747
1748 mailimap_response_free(response);
1749
1750 switch (error_code) {
1751 case MAILIMAP_RESP_COND_STATE_OK:
1752 return MAILIMAP_NO_ERROR;
1753
1754 default:
1755 return MAILIMAP_ERROR_STATUS;
1756 }
1757}
1758
1759
1760int
1761mailimap_store(mailimap * session,
1762 struct mailimap_set * set,
1763 struct mailimap_store_att_flags * store_att_flags)
1764{
1765 struct mailimap_response * response;
1766 int r;
1767 int error_code;
1768
1769 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1770 return MAILIMAP_ERROR_BAD_STATE;
1771
1772 r = send_current_tag(session);
1773 if (r != MAILIMAP_NO_ERROR)
1774 return r;
1775
1776 r = mailimap_store_send(session->imap_stream, set, store_att_flags);
1777 if (r != MAILIMAP_NO_ERROR)
1778 return r;
1779
1780 r = mailimap_crlf_send(session->imap_stream);
1781 if (r != MAILIMAP_NO_ERROR)
1782 return r;
1783
1784 if (mailstream_flush(session->imap_stream) == -1)
1785 return MAILIMAP_ERROR_STREAM;
1786
1787 if (read_line(session) == NULL)
1788 return MAILIMAP_ERROR_STREAM;
1789
1790 r = parse_response(session, &response);
1791 if (r != MAILIMAP_NO_ERROR)
1792 return r;
1793
1794 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1795
1796 mailimap_response_free(response);
1797
1798 switch (error_code) {
1799 case MAILIMAP_RESP_COND_STATE_OK:
1800 return MAILIMAP_NO_ERROR;
1801
1802 default:
1803 return MAILIMAP_ERROR_STORE;
1804 }
1805}
1806
1807int
1808mailimap_uid_store(mailimap * session,
1809 struct mailimap_set * set,
1810 struct mailimap_store_att_flags * store_att_flags)
1811{
1812 struct mailimap_response * response;
1813 int r;
1814 int error_code;
1815
1816 if (session->imap_state != MAILIMAP_STATE_SELECTED)
1817 return MAILIMAP_ERROR_BAD_STATE;
1818
1819 r = send_current_tag(session);
1820 if (r != MAILIMAP_NO_ERROR)
1821 return r;
1822
1823 r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags);
1824 if (r != MAILIMAP_NO_ERROR)
1825 return r;
1826
1827 r = mailimap_crlf_send(session->imap_stream);
1828 if (r != MAILIMAP_NO_ERROR)
1829 return r;
1830
1831 if (mailstream_flush(session->imap_stream) == -1)
1832 return MAILIMAP_ERROR_STREAM;
1833
1834 if (read_line(session) == NULL)
1835 return MAILIMAP_ERROR_STREAM;
1836
1837 r = parse_response(session, &response);
1838 if (r != MAILIMAP_NO_ERROR)
1839 return r;
1840
1841 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1842
1843 mailimap_response_free(response);
1844
1845 switch (error_code) {
1846 case MAILIMAP_RESP_COND_STATE_OK:
1847 return MAILIMAP_NO_ERROR;
1848
1849 default:
1850 return MAILIMAP_ERROR_UID_STORE;
1851 }
1852}
1853
1854int mailimap_subscribe(mailimap * session, const char * mb)
1855{
1856 struct mailimap_response * response;
1857 int r;
1858 int error_code;
1859
1860 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1861 (session->imap_state != MAILIMAP_STATE_SELECTED))
1862 return MAILIMAP_ERROR_BAD_STATE;
1863
1864 r = send_current_tag(session);
1865 if (r != MAILIMAP_NO_ERROR)
1866 return r;
1867
1868 r = mailimap_subscribe_send(session->imap_stream, mb);
1869 if (r != MAILIMAP_NO_ERROR)
1870 return r;
1871
1872 r = mailimap_crlf_send(session->imap_stream);
1873 if (r != MAILIMAP_NO_ERROR)
1874 return r;
1875
1876 if (mailstream_flush(session->imap_stream) == -1)
1877 return MAILIMAP_ERROR_STREAM;
1878
1879 if (read_line(session) == NULL)
1880 return MAILIMAP_ERROR_STREAM;
1881
1882 r = parse_response(session, &response);
1883 if (r != MAILIMAP_NO_ERROR)
1884 return r;
1885
1886 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1887
1888 mailimap_response_free(response);
1889
1890 switch (error_code) {
1891 case MAILIMAP_RESP_COND_STATE_OK:
1892 return MAILIMAP_NO_ERROR;
1893
1894 default:
1895 return MAILIMAP_ERROR_SUBSCRIBE;
1896 }
1897}
1898
1899int mailimap_unsubscribe(mailimap * session, const char * mb)
1900{
1901 struct mailimap_response * response;
1902 int r;
1903 int error_code;
1904
1905 if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) &&
1906 (session->imap_state != MAILIMAP_STATE_SELECTED))
1907 return MAILIMAP_ERROR_BAD_STATE;
1908
1909 r = send_current_tag(session);
1910 if (r != MAILIMAP_NO_ERROR)
1911 return r;
1912
1913 r = mailimap_unsubscribe_send(session->imap_stream, mb);
1914 if (r != MAILIMAP_NO_ERROR)
1915 return r;
1916
1917 r = mailimap_crlf_send(session->imap_stream);
1918 if (r != MAILIMAP_NO_ERROR)
1919 return r;
1920
1921 if (mailstream_flush(session->imap_stream) == -1)
1922 return MAILIMAP_ERROR_STREAM;
1923
1924 if (read_line(session) == NULL)
1925 return MAILIMAP_ERROR_STREAM;
1926
1927 r = parse_response(session, &response);
1928 if (r != MAILIMAP_NO_ERROR)
1929 return r;
1930
1931 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1932
1933 mailimap_response_free(response);
1934
1935 switch (error_code) {
1936 case MAILIMAP_RESP_COND_STATE_OK:
1937 return MAILIMAP_NO_ERROR;
1938
1939 default:
1940 return MAILIMAP_ERROR_UNSUBSCRIBE;
1941 }
1942}
1943
1944
1945int mailimap_starttls(mailimap * session)
1946{
1947 struct mailimap_response * response;
1948 int r;
1949 int error_code;
1950
1951 r = send_current_tag(session);
1952 if (r != MAILIMAP_NO_ERROR)
1953 return r;
1954
1955 r = mailimap_starttls_send(session->imap_stream);
1956 if (r != MAILIMAP_NO_ERROR)
1957 return r;
1958
1959 r = mailimap_crlf_send(session->imap_stream);
1960 if (r != MAILIMAP_NO_ERROR)
1961 return r;
1962
1963 if (mailstream_flush(session->imap_stream) == -1)
1964 return MAILIMAP_ERROR_STREAM;
1965
1966 if (read_line(session) == NULL)
1967 return MAILIMAP_ERROR_STREAM;
1968
1969 r = parse_response(session, &response);
1970 if (r != MAILIMAP_NO_ERROR)
1971 return r;
1972
1973 error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
1974
1975 mailimap_response_free(response);
1976
1977 switch (error_code) {
1978 case MAILIMAP_RESP_COND_STATE_OK:
1979 return MAILIMAP_NO_ERROR;
1980
1981 default:
1982 return MAILIMAP_ERROR_STARTTLS;
1983 }
1984}
1985
1986
1987
1988static char * read_line(mailimap * session)
1989{
1990 return mailstream_read_line(session->imap_stream, session->imap_stream_buffer);
1991}
1992
1993static int send_current_tag(mailimap * session)
1994{
1995 char tag_str[15];
1996 int r;
1997
1998 session->imap_tag ++;
1999 snprintf(tag_str, 15, "%i", session->imap_tag);
2000
2001 r = mailimap_tag_send(session->imap_stream, tag_str);
2002 if (r != MAILIMAP_NO_ERROR)
2003 return r;
2004
2005 r = mailimap_space_send(session->imap_stream);
2006 if (r != MAILIMAP_NO_ERROR)
2007 return r;
2008
2009 return MAILIMAP_NO_ERROR;
2010}
2011
2012static int parse_response(mailimap * session,
2013 struct mailimap_response ** result)
2014{
2015 size_t index;
2016 struct mailimap_response * response;
2017 char tag_str[15];
2018 int r;
2019
2020 index = 0;
2021
2022 session->imap_response = NULL;
2023
2024 r = mailimap_response_parse(session->imap_stream,
2025 session->imap_stream_buffer,
2026 &index, &response,
2027 session->imap_progr_rate, session->imap_progr_fun);
2028 if (r != MAILIMAP_NO_ERROR)
2029 return r;
2030
2031#if 0
2032 mailimap_response_print(response);
2033#endif
2034
2035 response_store(session, response);
2036
2037 if (mmap_string_assign(session->imap_response_buffer,
2038 response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text)
2039 == NULL)
2040 return MAILIMAP_ERROR_MEMORY;
2041
2042 session->imap_response = session->imap_response_buffer->str;
2043
2044 if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL)
2045 return MAILIMAP_ERROR_FATAL;
2046
2047 snprintf(tag_str, 15, "%i", session->imap_tag);
2048 if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0)
2049 return MAILIMAP_ERROR_PROTOCOL;
2050
2051 if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type ==
2052 MAILIMAP_RESP_COND_STATE_BAD)
2053 return MAILIMAP_ERROR_PROTOCOL;
2054
2055 * result = response;
2056
2057 return MAILIMAP_NO_ERROR;
2058}
2059
2060
2061static int parse_greeting(mailimap * session,
2062 struct mailimap_greeting ** result)
2063{
2064 size_t index;
2065 struct mailimap_greeting * greeting;
2066 int r;
2067
2068 index = 0;
2069
2070 session->imap_response = NULL;
2071
2072 r = mailimap_greeting_parse(session->imap_stream,
2073 session->imap_stream_buffer,
2074 &index, &greeting, session->imap_progr_rate,
2075 session->imap_progr_fun);
2076 if (r != MAILIMAP_NO_ERROR)
2077 return r;
2078
2079#if 0
2080 mailimap_greeting_print(greeting);
2081#endif
2082
2083 greeting_store(session, greeting);
2084
2085 if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) {
2086 if (mmap_string_assign(session->imap_response_buffer,
2087 greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL)
2088 return MAILIMAP_ERROR_MEMORY;
2089
2090 session->imap_response = session->imap_response_buffer->str;
2091
2092 return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION;
2093 }
2094
2095 if (mmap_string_assign(session->imap_response_buffer,
2096 greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL)
2097 return MAILIMAP_ERROR_MEMORY;
2098
2099 session->imap_response = session->imap_response_buffer->str;
2100
2101 * result = greeting;
2102
2103 return MAILIMAP_NO_ERROR;
2104}
2105
2106
2107mailimap * mailimap_new(size_t imap_progr_rate,
2108 progress_function * imap_progr_fun)
2109{
2110 mailimap * f;
2111
2112 f = malloc(sizeof(* f));
2113 if (f == NULL)
2114 goto err;
2115
2116 f->imap_response = NULL;
2117
2118 f->imap_stream = NULL;
2119
2120 f->imap_progr_rate = imap_progr_rate;
2121 f->imap_progr_fun = imap_progr_fun;
2122
2123 f->imap_stream_buffer = mmap_string_new("");
2124 if (f->imap_stream_buffer == NULL)
2125 goto free_f;
2126
2127 f->imap_response_buffer = mmap_string_new("");
2128 if (f->imap_response_buffer == NULL)
2129 goto free_stream_buffer;
2130
2131 f->imap_state = MAILIMAP_STATE_DISCONNECTED;
2132 f->imap_tag = 0;
2133
2134 f->imap_selection_info = NULL;
2135 f->imap_response_info = NULL;
2136 f->imap_connection_info = NULL;
2137
2138 return f;
2139
2140 free_stream_buffer:
2141 mmap_string_free(f->imap_stream_buffer);
2142 free_f:
2143 free(f);
2144 err:
2145 return NULL;
2146}
2147
2148void mailimap_free(mailimap * session)
2149{
2150 if (session->imap_stream)
2151 mailimap_logout(session);
2152
2153 mmap_string_free(session->imap_response_buffer);
2154 mmap_string_free(session->imap_stream_buffer);
2155
2156 if (session->imap_response_info)
2157 mailimap_response_info_free(session->imap_response_info);
2158 if (session->imap_selection_info)
2159 mailimap_selection_info_free(session->imap_selection_info);
2160 if (session->imap_connection_info)
2161 mailimap_connection_info_free(session->imap_connection_info);
2162
2163 free(session);
2164}
diff --git a/libetpan/src/low-level/imap/mailimap.h b/libetpan/src/low-level/imap/mailimap.h
new file mode 100644
index 0000000..e31e2d2
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap.h
@@ -0,0 +1,598 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_H
37
38#define MAILIMAP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45#include <libetpan/mailimap_types_helper.h>
46#include <libetpan/mailimap_helper.h>
47
48#include <libetpan/mailimap_socket.h>
49#include <libetpan/mailimap_ssl.h>
50
51/*
52 mailimap_connect()
53
54 This function will connect the IMAP session with the given stream.
55
56 @param session the IMAP session
57 @param s stream to use
58
59 @return the return code is one of MAILIMAP_ERROR_XXX or
60 MAILIMAP_NO_ERROR codes
61
62 note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or
63 MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned
64
65 MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to
66 use mailimap_login() to authenticate, else
67 MAILIMAP_NO_ERROR_AUTHENTICATED is returned.
68*/
69
70int mailimap_connect(mailimap * session, mailstream * s);
71
72/*
73 mailimap_append()
74
75 This function will append a given message to the given mailbox
76 by sending an APPEND command.
77
78 @param session the IMAP session
79 @param mailbox name of the mailbox
80 @param flag_list flags of the message
81 @param date_time timestamp of the message
82 @param literal content of the message
83 @param literal_size size of the message
84
85 @return the return code is one of MAILIMAP_ERROR_XXX or
86 MAILIMAP_NO_ERROR codes
87*/
88
89int mailimap_append(mailimap * session, const char * mailbox,
90 struct mailimap_flag_list * flag_list,
91 struct mailimap_date_time * date_time,
92 const char * literal, size_t literal_size);
93
94/*
95 mailimap_noop()
96
97 This function will poll for an event on the server by
98 sending a NOOP command to the IMAP server
99
100 @param session IMAP session
101
102 @return the return code is one of MAILIMAP_ERROR_XXX or
103 MAILIMAP_NO_ERROR_XXX codes
104*/
105
106int mailimap_noop(mailimap * session);
107
108/*
109 mailimap_logout()
110
111 This function will logout from an IMAP server by sending
112 a LOGOUT command.
113
114 @param session IMAP session
115
116 @return the return code is one of MAILIMAP_ERROR_XXX or
117 MAILIMAP_NO_ERROR codes
118*/
119
120int mailimap_logout(mailimap * session);
121
122/*
123 mailimap_capability()
124
125 This function will query an IMAP server for his capabilities
126 by sending a CAPABILITY command.
127
128 @param session IMAP session
129 @param result The result of this command is a list of
130 capabilities and it is stored into (* result).
131
132 @return the return code is one of MAILIMAP_ERROR_XXX or
133 MAILIMAP_NO_ERROR codes
134 */
135
136int mailimap_capability(mailimap * session,
137 struct mailimap_capability_data ** result);
138
139/*
140 mailimap_check()
141
142 This function will request for a checkpoint of the mailbox by
143 sending a CHECK command.
144
145 @param session IMAP session
146
147 @return the return code is one of MAILIMAP_ERROR_XXX or
148 MAILIMAP_NO_ERROR codes
149 */
150
151int mailimap_check(mailimap * session);
152
153/*
154 mailimap_close()
155
156 This function will close the selected mailbox by sending
157 a CLOSE command.
158
159 @param session IMAP session
160
161 @return the return code is one of MAILIMAP_ERROR_XXX or
162 MAILIMAP_NO_ERROR codes
163 */
164
165int mailimap_close(mailimap * session);
166
167/*
168 mailimap_expunge()
169
170 This function will permanently remove from the selected mailbox
171 message that have the \Deleted flag set.
172
173 @param session IMAP session
174
175 @return the return code is one of MAILIMAP_ERROR_XXX or
176 MAILIMAP_NO_ERROR codes
177*/
178
179int mailimap_expunge(mailimap * session);
180
181/*
182 mailimap_copy()
183
184 This function will copy the given messages from the selected mailbox
185 to the given mailbox.
186
187 @param session IMAP session
188 @param set This is a set of message numbers.
189 @param mb This is the destination mailbox.
190
191 @return the return code is one of MAILIMAP_ERROR_XXX or
192 MAILIMAP_NO_ERROR codes
193 */
194
195int mailimap_copy(mailimap * session, struct mailimap_set * set,
196 const char * mb);
197
198/*
199 mailimap_uid_copy()
200
201 This function will copy the given messages from the selected mailbox
202 to the given mailbox.
203
204 @param session IMAP session
205 @param set This is a set of message unique identifiers.
206 @param mb This is the destination mailbox.
207
208 @return the return code is one of MAILIMAP_ERROR_XXX or
209 MAILIMAP_NO_ERROR codes
210 */
211
212int mailimap_uid_copy(mailimap * session,
213 struct mailimap_set * set, const char * mb);
214
215/*
216 mailimap_create()
217
218 This function will create a mailbox.
219
220 @param session IMAP session
221 @param mb This is the name of the mailbox to create.
222
223 @return the return code is one of MAILIMAP_ERROR_XXX or
224 MAILIMAP_NO_ERROR codes
225*/
226
227int mailimap_create(mailimap * session, const char * mb);
228
229/*
230 mailimap_delete()
231
232 This function will delete a mailox.
233
234 @param session IMAP session
235 @param mb This is the name of the mailbox to delete.
236
237 @return the return code is one of MAILIMAP_ERROR_XXX or
238 MAILIMAP_NO_ERROR codes
239*/
240
241int mailimap_delete(mailimap * session, const char * mb);
242
243/*
244 mailimap_examine()
245
246 This function will select the mailbox for read-only operations.
247
248 @param session IMAP session
249 @param mb This is the name of the mailbox to select.
250
251 @return the return code is one of MAILIMAP_ERROR_XXX or
252 MAILIMAP_NO_ERROR codes
253*/
254
255int mailimap_examine(mailimap * session, const char * mb);
256
257/*
258 mailimap_fetch()
259
260 This function will retrieve data associated with the given message
261 numbers.
262
263 @param session IMAP session
264 @param set set of message numbers
265 @param fetch_type type of information to be retrieved
266 @param result The result of this command is a clist
267 and it is stored into (* result). Each element of the clist is a
268 (struct mailimap_msg_att *).
269
270 @return the return code is one of MAILIMAP_ERROR_XXX or
271 MAILIMAP_NO_ERROR codes
272*/
273
274int
275mailimap_fetch(mailimap * session, struct mailimap_set * set,
276 struct mailimap_fetch_type * fetch_type, clist ** result);
277
278/*
279 mailimap_fetch()
280
281 This function will retrieve data associated with the given message
282 numbers.
283
284 @param session IMAP session
285 @param set set of message unique identifiers
286 @param fetch_type type of information to be retrieved
287 @param result The result of this command is a clist
288 and it is stored into (* result). Each element of the clist is a
289 (struct mailimap_msg_att *).
290
291 @return the return code is one of MAILIMAP_ERROR_XXX or
292 MAILIMAP_NO_ERROR codes
293*/
294
295int
296mailimap_uid_fetch(mailimap * session,
297 struct mailimap_set * set,
298 struct mailimap_fetch_type * fetch_type, clist ** result);
299
300/*
301 mailimap_fetch_list_free()
302
303 This function will free the result of a fetch command.
304
305 @param fetch_list This is the clist containing
306 (struct mailimap_msg_att *) elements to free.
307*/
308
309void mailimap_fetch_list_free(clist * fetch_list);
310
311/*
312 mailimap_list()
313
314 This function will return the list of the mailbox
315 available on the server.
316
317 @param session IMAP session
318 @param mb This is the reference name that informs
319 of the level of hierarchy
320 @param list_mb mailbox name with possible wildcard
321 @param result This will store a clist of (struct mailimap_mailbox_list *)
322 in (* result)
323
324 @return the return code is one of MAILIMAP_ERROR_XXX or
325 MAILIMAP_NO_ERROR codes
326*/
327
328int mailimap_list(mailimap * session, const char * mb,
329 const char * list_mb, clist ** result);
330
331/*
332 mailimap_login()
333
334 This function will authenticate the client.
335
336 @param session IMAP session
337 @param userid login of the user
338 @param password password of the user
339
340 @return the return code is one of MAILIMAP_ERROR_XXX or
341 MAILIMAP_NO_ERROR codes
342*/
343
344int mailimap_login(mailimap * session,
345 const char * userid, const char * password);
346
347/*
348 mailimap_lsub()
349
350 This function will return the list of the mailbox
351 that the client has subscribed to.
352
353 @param session IMAP session
354 @param mb This is the reference name that informs
355 of the level of hierarchy
356 @param list_mb mailbox name with possible wildcard
357 @param result This will store a list of (struct mailimap_mailbox_list *)
358 in (* result)
359
360 @return the return code is one of MAILIMAP_ERROR_XXX or
361 MAILIMAP_NO_ERROR codes
362*/
363
364int mailimap_lsub(mailimap * session, const char * mb,
365 const char * list_mb, clist ** result);
366
367/*
368 mailimap_list_result_free()
369
370 This function will free the clist of (struct mailimap_mailbox_list *)
371
372 @param list This is the clist to free.
373*/
374
375void mailimap_list_result_free(clist * list);
376
377/*
378 mailimap_rename()
379
380 This function will change the name of a mailbox.
381
382 @param session IMAP session
383 @param mb current name
384 @param new_name new name
385
386 @return the return code is one of MAILIMAP_ERROR_XXX or
387 MAILIMAP_NO_ERROR codes
388*/
389
390int mailimap_rename(mailimap * session,
391 const char * mb, const char * new_name);
392
393/*
394 mailimap_search()
395
396 All mails that match the given criteria will be returned
397 their numbers in the result list.
398
399 @param session IMAP session
400 @param charset This indicates the charset of the strings that appears
401 in the searching criteria
402 @param key This is the searching criteria
403 @param result The result is a clist of (uint32_t *) and will be
404 stored in (* result).
405
406 @return the return code is one of MAILIMAP_ERROR_XXX or
407 MAILIMAP_NO_ERROR codes
408*/
409
410int
411mailimap_search(mailimap * session, const char * charset,
412 struct mailimap_search_key * key, clist ** result);
413
414/*
415 mailimap_uid_search()
416
417
418 All mails that match the given criteria will be returned
419 their unique identifiers in the result list.
420
421 @param session IMAP session
422 @param charset This indicates the charset of the strings that appears
423 in the searching criteria
424 @param key This is the searching criteria
425 @param result The result is a clist of (uint32_t *) and will be
426 stored in (* result).
427
428 @return the return code is one of MAILIMAP_ERROR_XXX or
429 MAILIMAP_NO_ERROR codes
430*/
431
432int
433mailimap_uid_search(mailimap * session, const char * charset,
434 struct mailimap_search_key * key, clist ** result);
435
436/*
437 mailimap_search_result_free()
438
439 This function will free the result of the a search.
440
441 @param search_result This is a clist of (uint32_t *) returned
442 by mailimap_uid_search() or mailimap_search()
443*/
444
445void mailimap_search_result_free(clist * search_result);
446
447/*
448 mailimap_select()
449
450 This function will select a given mailbox so that messages in the
451 mailbox can be accessed.
452
453 @param session IMAP session
454 @param mb This is the name of the mailbox to select.
455
456 @return the return code is one of MAILIMAP_ERROR_XXX or
457 MAILIMAP_NO_ERROR codes
458*/
459
460int
461mailimap_select(mailimap * session, const char * mb);
462
463/*
464 mailimap_status()
465
466 This function will return informations about a given mailbox.
467
468 @param session IMAP session
469 @param mb This is the name of the mailbox
470 @param status_att_list This is the list of mailbox information to return
471 @param result List of returned values
472
473 @return the return code is one of MAILIMAP_ERROR_XXX or
474 MAILIMAP_NO_ERROR codes
475*/
476
477int
478mailimap_status(mailimap * session, const char * mb,
479 struct mailimap_status_att_list * status_att_list,
480 struct mailimap_mailbox_data_status ** result);
481
482/*
483 mailimap_uid_store()
484
485 This function will alter the data associated with some messages
486 (flags of the messages).
487
488 @param session IMAP session
489 @param set This is a list of message numbers.
490 @param store_att_flags This is the data to associate with the
491 given messages
492
493 @return the return code is one of MAILIMAP_ERROR_XXX or
494 MAILIMAP_NO_ERROR codes
495*/
496
497int
498mailimap_store(mailimap * session,
499 struct mailimap_set * set,
500 struct mailimap_store_att_flags * store_att_flags);
501
502/*
503 mailimap_uid_store()
504
505 This function will alter the data associated with some messages
506 (flags of the messages).
507
508 @param session IMAP session
509 @param set This is a list of message unique identifiers.
510 @param store_att_flags This is the data to associate with the
511 given messages
512
513 @return the return code is one of MAILIMAP_ERROR_XXX or
514 MAILIMAP_NO_ERROR codes
515*/
516
517int
518mailimap_uid_store(mailimap * session,
519 struct mailimap_set * set,
520 struct mailimap_store_att_flags * store_att_flags);
521
522/*
523 mailimap_subscribe()
524
525 This function adds the specified mailbox name to the
526 server's set of "active" or "subscribed" mailboxes.
527
528 @param session IMAP session
529 @param mb This is the name of the mailbox
530
531 @return the return code is one of MAILIMAP_ERROR_XXX or
532 MAILIMAP_NO_ERROR codes
533*/
534
535int mailimap_subscribe(mailimap * session, const char * mb);
536
537/*
538 mailimap_unsubscribe()
539
540 This function removes the specified mailbox name to the
541 server's set of "active" or "subscribed" mailboxes.
542
543 @param session IMAP session
544 @param mb This is the name of the mailbox
545
546 @return the return code is one of MAILIMAP_ERROR_XXX or
547 MAILIMAP_NO_ERROR codes
548*/
549
550int mailimap_unsubscribe(mailimap * session, const char * mb);
551
552/*
553 mailimap_starttls()
554
555 This function starts change the mode of the connection to
556 switch to SSL connection.
557
558 @param session IMAP session
559
560 @return the return code is one of MAILIMAP_ERROR_XXX or
561 MAILIMAP_NO_ERROR_XXX codes
562 */
563
564int mailimap_starttls(mailimap * session);
565
566/*
567 mailimap_new()
568
569 This function returns a new IMAP session.
570
571 @param progr_rate When downloading messages, a function will be called
572 each time the amount of bytes downloaded reaches a multiple of this
573 value, this can be 0.
574 @param progr_fun This is the function to call to notify the progress,
575 this can be NULL.
576
577 @return an IMAP session is returned.
578 */
579
580mailimap * mailimap_new(size_t imap_progr_rate,
581 progress_function * imap_progr_fun);
582
583/*
584 mailimap_free()
585
586 This function will free the data structures associated with
587 the IMAP session.
588
589 @param session IMAP session
590 */
591
592void mailimap_free(mailimap * session);
593
594#ifdef __cplusplus
595}
596#endif
597
598#endif
diff --git a/libetpan/src/low-level/imap/mailimap_helper.c b/libetpan/src/low-level/imap/mailimap_helper.c
new file mode 100644
index 0000000..cc2a8e6
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_helper.c
@@ -0,0 +1,205 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_helper.h"
37
38#include <stdlib.h>
39#include "mailimap.h"
40
41int mailimap_fetch_rfc822(mailimap * session,
42 uint32_t msgid, char ** result)
43{
44 int r;
45 clist * fetch_list;
46 struct mailimap_fetch_att * fetch_att;
47 struct mailimap_fetch_type * fetch_type;
48 struct mailimap_set * set;
49 struct mailimap_msg_att * msg_att;
50 struct mailimap_msg_att_item * item;
51 int res;
52
53 fetch_att = mailimap_fetch_att_new_rfc822();
54 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
55 set = mailimap_set_new_single(msgid);
56
57 r = mailimap_fetch(session, set, fetch_type, &fetch_list);
58
59 mailimap_set_free(set);
60 mailimap_fetch_type_free(fetch_type);
61
62 if (r != MAILIMAP_NO_ERROR) {
63 res = r;
64 goto err;
65 }
66
67 if (clist_isempty(fetch_list)) {
68 res = MAILIMAP_ERROR_FETCH;
69 goto free;
70 }
71
72 msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data;
73
74 if (clist_isempty(msg_att->att_list)) {
75 res = MAILIMAP_ERROR_FETCH;
76 goto free;
77 }
78
79 item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data;
80
81 if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) {
82 res = MAILIMAP_ERROR_FETCH;
83 goto free;
84 }
85 if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822) {
86 res = MAILIMAP_ERROR_FETCH;
87 goto free;
88 }
89
90 * result = item->att_data.att_static->att_data.att_rfc822.att_content;
91 item->att_data.att_static->att_data.att_rfc822.att_content = NULL;
92 mailimap_fetch_list_free(fetch_list);
93
94 return MAILIMAP_NO_ERROR;
95
96free:
97 mailimap_fetch_list_free(fetch_list);
98err:
99 return res;
100}
101
102int mailimap_fetch_rfc822_header(mailimap * session,
103 uint32_t msgid, char ** result)
104{
105 int r;
106 int res;
107 clist * fetch_list;
108 struct mailimap_fetch_att * fetch_att;
109 struct mailimap_fetch_type * fetch_type;
110 struct mailimap_set * set;
111 struct mailimap_msg_att * msg_att;
112 struct mailimap_msg_att_item * item;
113
114 fetch_att = mailimap_fetch_att_new_rfc822_header();
115 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
116 set = mailimap_set_new_single(msgid);
117
118 r = mailimap_fetch(session, set, fetch_type, &fetch_list);
119
120 mailimap_set_free(set);
121 mailimap_fetch_type_free(fetch_type);
122
123 if (r != MAILIMAP_NO_ERROR) {
124 res = r;
125 goto err;
126 }
127
128 if (clist_isempty(fetch_list)) {
129 res = MAILIMAP_ERROR_FETCH;
130 goto free;
131 }
132
133 msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data;
134
135 if (clist_isempty(msg_att->att_list)) {
136 res = MAILIMAP_ERROR_FETCH;
137 goto free;
138 }
139
140 item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data;
141
142 if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) {
143 res = MAILIMAP_ERROR_FETCH;
144 goto err;
145 }
146
147 if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822_HEADER) {
148 res = MAILIMAP_ERROR_FETCH;
149 goto err;
150 }
151
152 * result = item->att_data.att_static->att_data.att_rfc822_header.att_content;
153 item->att_data.att_static->att_data.att_rfc822_header.att_content = NULL;
154 mailimap_fetch_list_free(fetch_list);
155
156 return MAILIMAP_NO_ERROR;
157
158free:
159 mailimap_fetch_list_free(fetch_list);
160err:
161 return res;
162}
163
164int mailimap_fetch_envelope(mailimap * session,
165 uint32_t first, uint32_t last,
166 clist ** result)
167{
168 int r;
169 clist * fetch_list;
170 struct mailimap_fetch_att * fetch_att;
171 struct mailimap_fetch_type * fetch_type;
172 struct mailimap_set * set;
173
174 fetch_att = mailimap_fetch_att_new_envelope();
175 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
176 set = mailimap_set_new_interval(first, last);
177
178 r = mailimap_fetch(session, set, fetch_type, &fetch_list);
179
180 mailimap_set_free(set);
181 mailimap_fetch_type_free(fetch_type);
182
183 if (r != MAILIMAP_NO_ERROR)
184 return r;
185
186 * result = fetch_list;
187
188 return MAILIMAP_NO_ERROR;
189}
190
191int mailimap_append_simple(mailimap * session, char * mailbox,
192 char * content, uint32_t size)
193{
194 return mailimap_append(session, mailbox, NULL, NULL, content, size);
195}
196
197int mailimap_login_simple(mailimap * session,
198 char * userid, char * password)
199{
200 if (session->imap_state == MAILIMAP_STATE_NON_AUTHENTICATED)
201 return mailimap_login(session, userid, password);
202 else
203 return MAILIMAP_NO_ERROR;
204}
205
diff --git a/libetpan/src/low-level/imap/mailimap_helper.h b/libetpan/src/low-level/imap/mailimap_helper.h
new file mode 100644
index 0000000..b548271
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_helper.h
@@ -0,0 +1,66 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_HELPER_H
37
38#define MAILIMAP_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45
46int mailimap_fetch_rfc822(mailimap * session,
47 uint32_t msgid, char ** result);
48
49int mailimap_fetch_rfc822_header(mailimap * session,
50 uint32_t msgid, char ** result);
51
52int mailimap_fetch_envelope(mailimap * session,
53 uint32_t first, uint32_t last,
54 clist ** result);
55
56int mailimap_append_simple(mailimap * session, char * mailbox,
57 char * content, uint32_t size);
58
59int mailimap_login_simple(mailimap * session,
60 char * userid, char * password);
61
62#ifdef __cplusplus
63}
64#endif
65
66#endif
diff --git a/libetpan/src/low-level/imap/mailimap_keywords.c b/libetpan/src/low-level/imap/mailimap_keywords.c
new file mode 100644
index 0000000..7e832a3
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_keywords.c
@@ -0,0 +1,353 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_keywords.h"
37#include "mailimap_types.h"
38#include <string.h>
39#include <stdio.h>
40
41#ifndef UNSTRICT_SYNTAX
42#define UNSTRICT_SYNTAX
43#endif
44
45struct mailimap_token_value {
46 int value;
47 const char * str;
48};
49
50int mailimap_token_case_insensitive_parse(mailstream * fd,
51 MMAPString * buffer,
52 size_t * index,
53 const char * token)
54{
55 int len;
56 size_t cur_token;
57 int r;
58
59 cur_token = * index;
60 len = strlen(token);
61
62#ifdef UNSTRICT_SYNTAX
63 r = mailimap_space_parse(fd, buffer, &cur_token);
64 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
65 return r;
66#endif
67
68 if (strncasecmp(buffer->str + cur_token, token, len) == 0) {
69 cur_token += len;
70 * index = cur_token;
71 return MAILIMAP_NO_ERROR;
72 }
73 else
74 return MAILIMAP_ERROR_PARSE;
75}
76
77
78static int is_space_or_tab(char ch)
79{
80 return (ch == ' ') || (ch == '\t');
81}
82
83int mailimap_char_parse(mailstream * fd, MMAPString * buffer,
84 size_t * index, char token)
85{
86 int cur_token;
87
88 cur_token = * index;
89
90 if (buffer->str[cur_token] == token) {
91 cur_token ++;
92 * index = cur_token;
93 return MAILIMAP_NO_ERROR;
94 }
95 else
96 return MAILIMAP_ERROR_PARSE;
97}
98
99int mailimap_space_parse(mailstream * fd, MMAPString * buffer,
100 size_t * index)
101{
102#ifdef UNSTRICT_SYNTAX
103
104 /* can accept unstrict syntax */
105 size_t cur_token;
106
107 cur_token = * index;
108
109 while (is_space_or_tab(* (buffer->str + cur_token)))
110 cur_token ++;
111
112 if (cur_token == * index)
113 return MAILIMAP_ERROR_PARSE;
114
115 * index = cur_token;
116
117 return MAILIMAP_NO_ERROR;
118
119#else
120 return mailimap_char_parse(fd, buffer, index, ' ');
121#endif
122}
123
124
125
126#define mailimap_get_token_str(index, tab) \
127 mailimap_get_token_str_size(index, tab, \
128 sizeof(tab) / sizeof(struct mailimap_token_value))
129
130#define mailimap_get_token_value(fd, buffer, index, tab) \
131 mailimap_get_token_value_size(fd, buffer, index, tab, \
132 sizeof(tab) / sizeof(struct mailimap_token_value))
133
134
135static const char * mailimap_get_token_str_size(int index,
136 struct mailimap_token_value * tab,
137 size_t size)
138{
139 size_t i;
140
141 for(i = 0 ; i < size ; i++)
142 if (index == tab[i].value)
143 return tab[i].str;
144
145 return NULL;
146}
147
148
149
150static int mailimap_get_token_value_size(mailstream * fd, MMAPString * buffer,
151 size_t * index,
152 struct mailimap_token_value * tab,
153 size_t size)
154{
155 size_t i;
156 int r;
157
158#ifdef UNSTRICT_SYNTAX
159 /* can accept unstrict syntax */
160 r = mailimap_space_parse(fd, buffer, index);
161 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
162 return r;
163#endif
164
165 for(i = 0 ; i < size ; i++) {
166 r = mailimap_token_case_insensitive_parse(fd, buffer, index, tab[i].str);
167 if (r == MAILIMAP_NO_ERROR)
168 return tab[i].value;
169 }
170
171 return -1;
172}
173
174
175static struct mailimap_token_value status_att_tab[] = {
176 {MAILIMAP_STATUS_ATT_MESSAGES, "MESSAGES"},
177 {MAILIMAP_STATUS_ATT_RECENT, "RECENT"},
178 {MAILIMAP_STATUS_ATT_UIDNEXT, "UIDNEXT"},
179 {MAILIMAP_STATUS_ATT_UIDVALIDITY, "UIDVALIDITY"},
180 {MAILIMAP_STATUS_ATT_UNSEEN, "UNSEEN"}
181};
182
183int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer,
184 size_t * index)
185{
186 int r;
187
188#ifdef UNSTRICT_SYNTAX
189 /* can accept unstrict syntax */
190 r = mailimap_space_parse(fd, buffer, index);
191 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
192 return r;
193#endif
194 return mailimap_get_token_value(fd, buffer, index,
195 status_att_tab);
196}
197
198
199const char * mailimap_status_att_get_token_str(size_t index)
200{
201 return mailimap_get_token_str(index, status_att_tab);
202}
203
204static struct mailimap_token_value month_tab[] = {
205 {1, "Jan"},
206 {2, "Feb"},
207 {3, "Mar"},
208 {4, "Apr"},
209 {5, "May"},
210 {6, "Jun"},
211 {7, "Jul"},
212 {8, "Aug"},
213 {9, "Sep"},
214 {10, "Oct"},
215 {11, "Nov"},
216 {12, "Dec"}
217};
218
219int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer,
220 size_t * index)
221{
222 return mailimap_get_token_value(fd, buffer, index, month_tab);
223}
224
225
226const char * mailimap_month_get_token_str(size_t index)
227{
228 return mailimap_get_token_str(index, month_tab);
229}
230
231
232
233
234
235static struct mailimap_token_value mailimap_flag_tab[] = {
236 {MAILIMAP_FLAG_ANSWERED, "\\Answered"},
237 {MAILIMAP_FLAG_FLAGGED, "\\Flagged"},
238 {MAILIMAP_FLAG_DELETED, "\\Deleted"},
239 {MAILIMAP_FLAG_SEEN, "\\Seen"},
240 {MAILIMAP_FLAG_DRAFT, "\\Draft"}
241};
242
243int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer,
244 size_t * index)
245{
246 return mailimap_get_token_value(fd, buffer, index,
247 mailimap_flag_tab);
248}
249
250
251const char * mailimap_flag_get_token_str(size_t index)
252{
253 return mailimap_get_token_str(index, mailimap_flag_tab);
254}
255
256
257
258
259static struct mailimap_token_value encoding_tab[] = {
260 {MAILIMAP_BODY_FLD_ENC_7BIT, "7BIT"},
261 {MAILIMAP_BODY_FLD_ENC_8BIT, "8BIT"},
262 {MAILIMAP_BODY_FLD_ENC_BINARY, "BINARY"},
263 {MAILIMAP_BODY_FLD_ENC_BASE64, "BASE64"},
264 {MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, "QUOTED-PRINTABLE"}
265};
266
267int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer,
268 size_t * index)
269{
270 return mailimap_get_token_value(fd, buffer, index, encoding_tab);
271}
272
273static struct mailimap_token_value mbx_list_sflag_tab[] = {
274 {MAILIMAP_MBX_LIST_SFLAG_MARKED, "\\Marked"},
275 {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "\\Noselect"},
276 {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "\\Unmarked"}
277};
278
279int mailimap_mbx_list_sflag_get_token_value(mailstream * fd,
280 MMAPString * buffer,
281 size_t * index)
282{
283 return mailimap_get_token_value(fd, buffer, index, mbx_list_sflag_tab);
284}
285
286static struct mailimap_token_value media_basic_tab[] = {
287 {MAILIMAP_MEDIA_BASIC_APPLICATION, "APPLICATION"},
288 {MAILIMAP_MEDIA_BASIC_AUDIO, "AUDIO"},
289 {MAILIMAP_MEDIA_BASIC_IMAGE, "IMAGE"},
290 {MAILIMAP_MEDIA_BASIC_MESSAGE, "MESSAGE"},
291 {MAILIMAP_MEDIA_BASIC_VIDEO, "VIDEO"}
292};
293
294int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer,
295 size_t * index)
296{
297 return mailimap_get_token_value(fd, buffer, index, media_basic_tab);
298}
299
300static struct mailimap_token_value resp_cond_state_tab[] = {
301 {MAILIMAP_RESP_COND_STATE_OK, "OK"},
302 {MAILIMAP_RESP_COND_STATE_NO, "NO"},
303 {MAILIMAP_RESP_COND_STATE_BAD, "BAD"}
304};
305
306int mailimap_resp_cond_state_get_token_value(mailstream * fd,
307 MMAPString * buffer,
308 size_t * index)
309{
310 return mailimap_get_token_value(fd, buffer, index, resp_cond_state_tab);
311}
312
313static struct mailimap_token_value resp_text_code_1_tab[] = {
314 {MAILIMAP_RESP_TEXT_CODE_ALERT, "ALERT"},
315 {MAILIMAP_RESP_TEXT_CODE_PARSE, "PARSE"},
316 {MAILIMAP_RESP_TEXT_CODE_READ_ONLY, "READ-ONLY"},
317 {MAILIMAP_RESP_TEXT_CODE_READ_WRITE, "READ-WRITE"},
318 {MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, "TRYCREATE"}
319};
320
321int mailimap_resp_text_code_1_get_token_value(mailstream * fd,
322 MMAPString * buffer,
323 size_t * index)
324{
325 return mailimap_get_token_value(fd, buffer, index, resp_text_code_1_tab);
326}
327
328static struct mailimap_token_value resp_text_code_2_tab[] = {
329 {MAILIMAP_RESP_TEXT_CODE_UIDNEXT, "UIDNEXT"},
330 {MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, "UIDVALIDITY"},
331 {MAILIMAP_RESP_TEXT_CODE_UNSEEN, "UNSEEN"},
332};
333
334int mailimap_resp_text_code_2_get_token_value(mailstream * fd,
335 MMAPString * buffer,
336 size_t * index)
337{
338 return mailimap_get_token_value(fd, buffer, index, resp_text_code_2_tab);
339}
340
341static struct mailimap_token_value section_msgtext_tab[] = {
342 {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, "HEADER.FIELDS.NOT"},
343 {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, "HEADER.FIELDS"},
344 {MAILIMAP_SECTION_MSGTEXT_HEADER, "HEADER"},
345 {MAILIMAP_SECTION_MSGTEXT_TEXT, "TEXT"}
346};
347
348int mailimap_section_msgtext_get_token_value(mailstream * fd,
349 MMAPString * buffer,
350 size_t * index)
351{
352 return mailimap_get_token_value(fd, buffer, index, section_msgtext_tab);
353}
diff --git a/libetpan/src/low-level/imap/mailimap_keywords.h b/libetpan/src/low-level/imap/mailimap_keywords.h
new file mode 100644
index 0000000..e00f687
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_keywords.h
@@ -0,0 +1,107 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_COMMON_H
37
38#define MAILIMAP_COMMON_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstream.h"
45
46
47/* tools */
48
49int mailimap_char_parse(mailstream * fd, MMAPString * buffer,
50 size_t * index, char token);
51
52int mailimap_space_parse(mailstream * fd, MMAPString * buffer,
53 size_t * index);
54
55/* tokens */
56
57int mailimap_token_case_insensitive_parse(mailstream * fd,
58 MMAPString * buffer,
59 size_t * index,
60 const char * token);
61
62int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer,
63 size_t * index);
64const char * mailimap_status_att_get_token_str(size_t index);
65
66
67int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer,
68 size_t * index);
69const char * mailimap_month_get_token_str(size_t index);
70
71
72int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer,
73 size_t * index);
74
75const char * mailimap_flag_get_token_str(size_t index);
76
77int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer,
78 size_t * index);
79
80int mailimap_mbx_list_sflag_get_token_value(mailstream * fd,
81 MMAPString * buffer,
82 size_t * index);
83
84int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer,
85 size_t * index);
86
87int mailimap_resp_cond_state_get_token_value(mailstream * fd,
88 MMAPString * buffer,
89 size_t * index);
90
91int mailimap_resp_text_code_1_get_token_value(mailstream * fd,
92 MMAPString * buffer,
93 size_t * index);
94
95int mailimap_resp_text_code_2_get_token_value(mailstream * fd,
96 MMAPString * buffer,
97 size_t * index);
98
99int mailimap_section_msgtext_get_token_value(mailstream * fd,
100 MMAPString * buffer,
101 size_t * index);
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif
diff --git a/libetpan/src/low-level/imap/mailimap_parser.c b/libetpan/src/low-level/imap/mailimap_parser.c
new file mode 100644
index 0000000..ab4db67
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_parser.c
@@ -0,0 +1,9506 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include <string.h>
37#include <stdlib.h>
38#include <stdio.h>
39
40#include "mailstream.h"
41#include "mailimap_keywords.h"
42#include "mailimap_parser.h"
43#include "mmapstring.h"
44#include "mail.h"
45
46#ifndef UNSTRICT_SYNTAX
47#define UNSTRICT_SYNTAX
48#endif
49
50/*
51 Document: internet-drafts/draft-crispin-imapv-15.txt
52 RFC 2060 (IMAP but rather used draft)
53 RFC 2234 for all token that are not defined such as ALPHA
54*/
55
56
57
58/* ************************************************************************* */
59/* ************************************************************************* */
60/* ************************************************************************* */
61/* ************************************************************************* */
62/* ************************************************************************* */
63/* ************************************************************************* */
64
65
66
67
68static int mailimap_address_parse(mailstream * fd, MMAPString * buffer,
69 size_t * index,
70 struct mailimap_address ** result,
71 size_t progr_rate,
72 progress_function * progr_fun);
73
74static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer,
75 size_t * index, char ** result,
76 size_t progr_rate,
77 progress_function * progr_fun);
78
79static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer,
80 size_t * index, char ** result,
81 size_t progr_rate,
82 progress_function * progr_fun);
83
84static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer,
85 size_t * index, char ** result,
86 size_t progr_rate,
87 progress_function * progr_fun);
88
89static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer,
90 size_t * index, char ** result,
91 size_t progr_rate,
92 progress_function * progr_fun);
93
94
95static int
96mailimap_astring_parse(mailstream * fd, MMAPString * buffer,
97 size_t * index,
98 char ** result,
99 size_t progr_rate,
100 progress_function * progr_fun);
101
102static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer,
103 size_t * index, char ** result,
104 size_t progr_rate,
105 progress_function * progr_fun);
106
107static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer,
108 size_t * index, char ** result,
109 size_t progr_rate,
110 progress_function * progr_fun);
111
112static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer,
113 size_t * index, char ** result,
114 size_t progr_rate,
115 progress_function * progr_fun);
116
117static int mailimap_body_parse(mailstream * fd, MMAPString * buffer,
118 size_t * index,
119 struct mailimap_body ** result,
120 size_t progr_rate,
121 progress_function * progr_fun);
122
123
124static int
125mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer,
126 size_t * index,
127 struct mailimap_body_extension ** result,
128 size_t progr_rate,
129 progress_function * progr_fun);
130
131
132static int
133mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer,
134 size_t * index,
135 struct mailimap_body_ext_1part ** result,
136 size_t progr_rate,
137 progress_function * progr_fun);
138
139
140
141static int
142mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer,
143 size_t * index,
144 struct mailimap_body_ext_mpart ** result,
145 size_t progr_rate,
146 progress_function * progr_fun);
147
148
149static int
150mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer,
151 size_t * index,
152 struct mailimap_body_fields ** result,
153 size_t progr_rate,
154 progress_function * progr_fun);
155
156static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer,
157 size_t * index, char ** result,
158 size_t progr_rate,
159 progress_function * progr_fun);
160
161
162static int
163mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer,
164 size_t * index,
165 struct mailimap_body_fld_dsp ** result,
166 size_t progr_rate,
167 progress_function * progr_fun);
168
169
170
171static int
172mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer,
173 size_t * index,
174 struct mailimap_body_fld_enc ** result,
175 size_t progr_rate,
176 progress_function * progr_fun);
177
178
179
180static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer,
181 size_t * index, char ** result,
182 size_t progr_rate,
183 progress_function * progr_fun);
184
185
186static int
187mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer,
188 size_t * index,
189 struct mailimap_body_fld_lang ** result,
190 size_t progr_rate,
191 progress_function * progr_fun);
192
193static int mailimap_body_fld_lines_parse(mailstream * fd,
194 MMAPString * buffer, size_t * index,
195 uint32_t * result);
196
197static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer,
198 size_t * index, char ** result,
199 size_t progr_rate,
200 progress_function * progr_fun);
201
202static int mailimap_body_fld_octets_parse(mailstream * fd,
203 MMAPString * buffer, size_t * index,
204 uint32_t * result);
205
206static int
207mailimap_body_fld_param_parse(mailstream * fd,
208 MMAPString * buffer, size_t * index,
209 struct mailimap_body_fld_param ** result,
210 size_t progr_rate,
211 progress_function * progr_fun);
212
213
214
215static int
216mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer,
217 size_t * index,
218 struct mailimap_body_type_1part ** result,
219 size_t progr_rate,
220 progress_function * progr_fun);
221
222
223
224static int
225mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer,
226 size_t * index,
227 struct mailimap_body_type_basic ** result,
228 size_t progr_rate,
229 progress_function * progr_fun);
230
231
232
233static int
234mailimap_body_type_mpart_parse(mailstream * fd,
235 MMAPString * buffer,
236 size_t * index,
237 struct mailimap_body_type_mpart ** result,
238 size_t progr_rate,
239 progress_function * progr_fun);
240
241
242
243static int
244mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer,
245 size_t * index,
246 struct mailimap_body_type_msg ** result,
247 size_t progr_rate,
248 progress_function * progr_fun);
249
250
251
252static int
253mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer,
254 size_t * index,
255 struct mailimap_body_type_text **
256 result,
257 size_t progr_rate,
258 progress_function * progr_fun);
259
260
261
262static int
263mailimap_capability_parse(mailstream * fd, MMAPString * buffer,
264 size_t * index,
265 struct mailimap_capability ** result,
266 size_t progr_rate,
267 progress_function * progr_fun);
268
269
270
271static int
272mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer,
273 size_t * index,
274 struct mailimap_capability_data ** result,
275 size_t progr_rate,
276 progress_function * progr_fun);
277
278
279/*
280static gboolean mailimap_date_day_parse(mailstream * fd,
281 MMAPString * buffer,
282 guint32 * index,
283 gint * result);
284*/
285static int mailimap_date_day_fixed_parse(mailstream * fd,
286 MMAPString * buffer,
287 size_t * index,
288 int * result);
289
290static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer,
291 size_t * index, int * result);
292
293/*
294struct mailimap_date_text {
295 gint day;
296 gint month;
297 gint year;
298};
299
300static gboolean
301mailimap_date_text_parse(mailstream * fd, MMAPString * buffer,
302 guint32 * index, struct mailimap_date_text ** result);
303static void mailimap_date_text_free(struct mailimap_date_text * date_text);
304*/
305
306static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer,
307 size_t * index, int * result);
308
309static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer,
310 size_t * index,
311 struct mailimap_date_time ** t,
312 size_t progr_rate,
313 progress_function * progr_fun);
314
315#ifndef UNSTRICT_SYNTAX
316static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer,
317 size_t * index, int * result);
318#endif
319
320
321static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer,
322 size_t * index,
323 struct mailimap_envelope ** result,
324 size_t progr_rate,
325 progress_function * progr_fun);
326
327
328static int
329mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer,
330 size_t * index, struct mailimap_env_bcc ** result,
331 size_t progr_rate,
332 progress_function * progr_fun);
333
334
335static int
336mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer,
337 size_t * index, struct mailimap_env_cc ** result,
338 size_t progr_rate,
339 progress_function * progr_fun);
340
341static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer,
342 size_t * index, char ** result,
343 size_t progr_rate,
344 progress_function * progr_fun);
345
346
347static int
348mailimap_env_from_parse(mailstream * fd, MMAPString * buffer,
349 size_t * index, struct mailimap_env_from ** result,
350 size_t progr_rate,
351 progress_function * progr_fun);
352
353
354static int mailimap_env_in_reply_to_parse(mailstream * fd,
355 MMAPString * buffer,
356 size_t * index, char ** result,
357 size_t progr_rate,
358 progress_function * progr_fun);
359
360static int mailimap_env_message_id_parse(mailstream * fd,
361 MMAPString * buffer,
362 size_t * index, char ** result,
363 size_t progr_rate,
364 progress_function * progr_fun);
365
366static int
367mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer,
368 size_t * index,
369 struct mailimap_env_reply_to ** result,
370 size_t progr_rate,
371 progress_function * progr_fun);
372
373
374
375static int
376mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer,
377 size_t * index, struct mailimap_env_sender ** result,
378 size_t progr_rate,
379 progress_function * progr_fun);
380
381static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer,
382 size_t * index, char ** result,
383 size_t progr_rate,
384 progress_function * progr_fun);
385
386
387static int
388mailimap_env_to_parse(mailstream * fd, MMAPString * buffer,
389 size_t * index,
390 struct mailimap_env_to ** result,
391 size_t progr_rate,
392 progress_function * progr_fun);
393
394
395static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer,
396 size_t * index,
397 struct mailimap_flag ** result,
398 size_t progr_rate,
399 progress_function * progr_fun);
400
401static int mailimap_flag_extension_parse(mailstream * fd,
402 MMAPString * buffer,
403 size_t * index,
404 char ** result,
405 size_t progr_rate,
406 progress_function * progr_fun);
407
408
409
410
411static int
412mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer,
413 size_t * index,
414 struct mailimap_flag_fetch ** result,
415 size_t progr_rate,
416 progress_function * progr_fun);
417
418
419
420static int
421mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer,
422 size_t * index,
423 struct mailimap_flag_perm ** result,
424 size_t progr_rate,
425 progress_function * progr_fun);
426
427
428static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer,
429 size_t * index,
430 char ** result,
431 size_t progr_rate,
432 progress_function * progr_fun);
433
434
435static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer,
436 size_t * index,
437 struct mailimap_flag_list ** result,
438 size_t progr_rate,
439 progress_function * progr_fun);
440
441
442static int
443mailimap_header_fld_name_parse(mailstream * fd,
444 MMAPString * buffer,
445 size_t * index,
446 char ** result,
447 size_t progr_rate,
448 progress_function * progr_fun);
449
450
451
452
453static int
454mailimap_header_list_parse(mailstream * fd, MMAPString * buffer,
455 size_t * index,
456 struct mailimap_header_list ** result,
457 size_t progr_rate,
458 progress_function * progr_fun);
459
460static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer,
461 size_t * index, char ** result,
462 size_t * result_len,
463 size_t progr_rate,
464 progress_function * progr_fun);
465
466
467static int
468mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer,
469 size_t * index, char ** result,
470 size_t progr_rate,
471 progress_function * progr_fun);
472
473
474
475
476static int
477mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer,
478 size_t * index,
479 struct mailimap_mailbox_data ** result,
480 size_t progr_rate,
481 progress_function * progr_fun);
482
483
484static int
485mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer,
486 size_t * index,
487 struct mailimap_mbx_list_flags ** result,
488 size_t progr_rate,
489 progress_function * progr_fun);
490
491
492static int
493mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer,
494 size_t * index,
495 struct mailimap_mbx_list_oflag ** result,
496 size_t progr_rate,
497 progress_function * progr_fun);
498
499static int
500mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer,
501 size_t * index,
502 struct mailimap_mbx_list_oflag ** result,
503 size_t progr_rate,
504 progress_function * progr_fun);
505
506static int
507mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer,
508 size_t * index,
509 int * result);
510
511
512static int
513mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer,
514 size_t * index,
515 struct mailimap_mailbox_list ** result,
516 size_t progr_rate,
517 progress_function * progr_fun);
518
519
520
521static int
522mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer,
523 size_t * index,
524 struct mailimap_media_basic ** result,
525 size_t progr_rate,
526 progress_function * progr_fun);
527
528static int
529mailimap_media_message_parse(mailstream * fd, MMAPString * buffer,
530 size_t * index);
531
532static int
533mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer,
534 size_t * index,
535 char ** result,
536 size_t progr_rate,
537 progress_function * progr_fun);
538
539static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer,
540 size_t * index,
541 char ** result,
542 size_t progr_rate,
543 progress_function * progr_fun);
544
545
546
547static int
548mailimap_message_data_parse(mailstream * fd, MMAPString * buffer,
549 size_t * index,
550 struct mailimap_message_data ** result,
551 size_t progr_rate,
552 progress_function * progr_fun);
553
554
555
556
557
558static int
559mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer,
560 size_t * index, struct mailimap_msg_att ** result,
561 size_t progr_rate,
562 progress_function * progr_fun);
563
564
565
566static int
567mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer,
568 size_t * index,
569 struct mailimap_msg_att_dynamic ** result,
570 size_t progr_rate,
571 progress_function * progr_fun);
572
573
574static int
575mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer,
576 size_t * index,
577 struct mailimap_msg_att_static ** result,
578 size_t progr_rate,
579 progress_function * progr_fun);
580
581static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer,
582 size_t * index);
583
584static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer,
585 size_t * index, char ** result,
586 size_t * result_len,
587 size_t progr_rate,
588 progress_function * progr_fun);
589
590static int
591mailimap_number_parse(mailstream * fd, MMAPString * buffer,
592 size_t * index, uint32_t * result);
593
594static int
595mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer,
596 size_t * index, uint32_t * result);
597
598
599static int
600mailimap_quoted_parse(mailstream * fd, MMAPString * buffer,
601 size_t * index, char ** result,
602 size_t progr_rate,
603 progress_function * progr_fun);
604
605static int
606mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer,
607 size_t * index, char * result);
608
609
610static int
611mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer,
612 size_t * index, char * result);
613
614
615
616
617
618static int
619mailimap_response_data_parse(mailstream * fd, MMAPString * buffer,
620 size_t * index,
621 struct mailimap_response_data ** result,
622 size_t progr_rate,
623 progress_function * progr_fun);
624
625
626
627
628static int
629mailimap_response_done_parse(mailstream * fd, MMAPString * buffer,
630 size_t * index,
631 struct mailimap_response_done ** result,
632 size_t progr_rate,
633 progress_function * progr_fun);
634
635static int
636mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer,
637 size_t * index,
638 struct mailimap_response_fatal ** result,
639 size_t progr_rate,
640 progress_function * progr_fun);
641
642
643static int
644mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer,
645 size_t * index,
646 struct mailimap_response_tagged ** result,
647 size_t progr_rate,
648 progress_function * progr_fun);
649
650
651static int
652mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer,
653 size_t * index,
654 struct mailimap_resp_cond_auth ** result,
655 size_t progr_rate,
656 progress_function * progr_fun);
657
658static int
659mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer,
660 size_t * index,
661 struct mailimap_resp_cond_bye ** result,
662 size_t progr_rate,
663 progress_function * progr_fun);
664
665
666static int
667mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer,
668 size_t * index,
669 struct mailimap_resp_cond_state ** result,
670 size_t progr_rate,
671 progress_function * progr_fun);
672
673
674static int
675mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer,
676 size_t * index,
677 struct mailimap_resp_text ** result,
678 size_t progr_rate,
679 progress_function * progr_fun);
680
681
682static int
683mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
684 size_t * index,
685 struct mailimap_resp_text_code ** result,
686 size_t progr_rate,
687 progress_function * progr_fun);
688
689
690static int
691mailimap_section_parse(mailstream * fd, MMAPString * buffer,
692 size_t * index,
693 struct mailimap_section ** result,
694 size_t progr_rate,
695 progress_function * progr_fun);
696
697
698static int
699mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer,
700 size_t * index,
701 struct mailimap_section_msgtext ** result,
702 size_t progr_rate,
703 progress_function * progr_fun);
704
705
706static int
707mailimap_section_part_parse(mailstream * fd, MMAPString * buffer,
708 size_t * index,
709 struct mailimap_section_part ** result,
710 size_t progr_rate,
711 progress_function * progr_fun);
712
713
714
715
716static int
717mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer,
718 size_t * index,
719 struct mailimap_section_spec ** result,
720 size_t progr_rate,
721 progress_function * progr_fun);
722
723
724static int
725mailimap_section_text_parse(mailstream * fd, MMAPString * buffer,
726 size_t * index,
727 struct mailimap_section_text ** result,
728 size_t progr_rate,
729 progress_function * progr_fun);
730
731
732static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer,
733 size_t * index, int * result);
734
735static int
736mailimap_string_parse(mailstream * fd, MMAPString * buffer,
737 size_t * index, char ** result,
738 size_t * result_len,
739 size_t progr_rate,
740 progress_function * progr_fun);
741
742static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer,
743 size_t * index, char ** result,
744 size_t progr_rate,
745 progress_function * progr_fun);
746
747static int mailimap_text_parse(mailstream * fd, MMAPString * buffer,
748 size_t * index, char ** result,
749 size_t progr_rate,
750 progress_function * progr_fun);
751
752static int mailimap_time_parse(mailstream * fd, MMAPString * buffer,
753 size_t * index,
754 int * phour, int * pmin, int * psec);
755
756static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer,
757 size_t * index, uint32_t * result);
758
759static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer,
760 size_t * index, int * result);
761
762
763
764/* ************************************************************************* */
765/* ************************************************************************* */
766/* ************************************************************************* */
767/* ************************************************************************* */
768/* ************************************************************************* */
769/* ************************************************************************* */
770
771
772
773
774
775/* ******************** TOOLS **************************** */
776
777
778static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer,
779 size_t * index, char token)
780{
781 size_t cur_token;
782 int r;
783
784 cur_token = * index;
785
786#ifdef UNSTRICT_SYNTAX
787 /* can accept unstrict syntax */
788
789 mailimap_space_parse(fd, buffer, &cur_token);
790 if (token == ' ') {
791 * index = cur_token;
792 return MAILIMAP_NO_ERROR;
793 }
794#endif
795
796 r = mailimap_char_parse(fd, buffer, &cur_token, token);
797 if (r != MAILIMAP_NO_ERROR)
798 return r;
799
800 * index = cur_token;
801
802 return MAILIMAP_NO_ERROR;
803}
804
805static int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer,
806 size_t * index)
807{
808 return mailimap_unstrict_char_parse(fd, buffer, index, '(');
809}
810
811static int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer,
812 size_t * index)
813{
814 return mailimap_unstrict_char_parse(fd, buffer, index, ')');
815}
816
817static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer,
818 size_t * index)
819{
820 return mailimap_unstrict_char_parse(fd, buffer, index, '{');
821}
822
823static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer,
824 size_t * index)
825{
826 return mailimap_unstrict_char_parse(fd, buffer, index, '}');
827}
828
829static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer,
830 size_t * index)
831{
832 return mailimap_unstrict_char_parse(fd, buffer, index, '+');
833}
834
835static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer,
836 size_t * index)
837{
838 return mailimap_unstrict_char_parse(fd, buffer, index, '-');
839}
840
841static int mailimap_star_parse(mailstream * fd, MMAPString * buffer,
842 size_t * index)
843{
844 return mailimap_unstrict_char_parse(fd, buffer, index, '*');
845}
846
847static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer,
848 size_t * index)
849{
850 return mailimap_unstrict_char_parse(fd, buffer, index, '.');
851}
852
853static int mailimap_colon_parse(mailstream * fd, MMAPString * buffer,
854 size_t * index)
855{
856 return mailimap_unstrict_char_parse(fd, buffer, index, ':');
857}
858
859static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer,
860 size_t * index)
861{
862 return mailimap_unstrict_char_parse(fd, buffer, index, '<');
863}
864
865static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer,
866 size_t * index)
867{
868 return mailimap_unstrict_char_parse(fd, buffer, index, '>');
869}
870
871static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer,
872 size_t * index)
873{
874 return mailimap_unstrict_char_parse(fd, buffer, index, '[');
875}
876
877static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer,
878 size_t * index)
879{
880 return mailimap_unstrict_char_parse(fd, buffer, index, ']');
881}
882
883static int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer,
884 size_t * index)
885{
886 return mailimap_char_parse(fd, buffer, index, '\"');
887}
888
889static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer,
890 size_t * index)
891{
892 size_t cur_token = * index;
893
894#ifdef UNSTRICT_SYNTAX
895 mailimap_space_parse(fd, buffer, &cur_token);
896#endif
897
898 if (mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n")) {
899 * index = cur_token;
900 return MAILIMAP_NO_ERROR;
901 }
902
903#ifdef UNSTRICT_SYNTAX
904 else if (mailimap_unstrict_char_parse(fd, buffer, &cur_token, '\n')) {
905 * index = cur_token;
906 return MAILIMAP_NO_ERROR;
907 }
908#endif
909
910 else
911 return MAILIMAP_ERROR_PARSE;
912}
913
914typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer,
915 size_t * index, void * result,
916 size_t progr_rate,
917 progress_function * progr_fun);
918typedef int mailimap_struct_destructor(void * result);
919
920
921static int
922mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer,
923 size_t * index, clist ** result,
924 mailimap_struct_parser * parser,
925 mailimap_struct_destructor * destructor,
926 size_t progr_rate,
927 progress_function * progr_fun)
928{
929 clist * struct_list;
930 size_t cur_token;
931 void * value;
932 int r;
933 int res;
934
935 cur_token = * index;
936
937 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
938 if (r != MAILIMAP_NO_ERROR) {
939 res = r;
940 goto err;
941 }
942
943 struct_list = clist_new();
944 if (struct_list == NULL) {
945 destructor(value);
946 res = MAILIMAP_ERROR_MEMORY;
947 goto err;
948 }
949
950 r = clist_append(struct_list, value);
951 if (r < 0) {
952 destructor(value);
953 res = MAILIMAP_ERROR_MEMORY;
954 goto free_list;
955 }
956
957 while (1) {
958 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
959 if (r == MAILIMAP_ERROR_PARSE)
960 break;
961 if (r != MAILIMAP_NO_ERROR) {
962 res = r;
963 goto free_list;
964 }
965
966 r = clist_append(struct_list, value);
967 if (r < 0) {
968 destructor(value);
969 res = MAILIMAP_ERROR_MEMORY;
970 goto free_list;
971 }
972 }
973
974 * result = struct_list;
975 * index = cur_token;
976
977 return MAILIMAP_NO_ERROR;
978
979 free_list:
980 clist_foreach(struct_list, (clist_func) destructor, NULL);
981 clist_free(struct_list);
982 err:
983 return res;
984}
985
986static int
987mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer,
988 size_t * index, clist ** result,
989 char symbol,
990 mailimap_struct_parser * parser,
991 mailimap_struct_destructor * destructor,
992 size_t progr_rate,
993 progress_function * progr_fun)
994{
995 clist * struct_list;
996 size_t cur_token;
997 void * value;
998 size_t final_token;
999 int r;
1000 int res;
1001
1002 cur_token = * index;
1003 struct_list = NULL;
1004
1005 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
1006 if (r != MAILIMAP_NO_ERROR) {
1007 res = r;
1008 goto err;
1009 }
1010
1011 struct_list = clist_new();
1012 if (struct_list == NULL) {
1013 destructor(value);
1014 res = MAILIMAP_ERROR_MEMORY;
1015 goto err;
1016 }
1017
1018 r = clist_append(struct_list, value);
1019 if (r < 0) {
1020 destructor(value);
1021 res = MAILIMAP_ERROR_MEMORY;
1022 goto free_list;
1023 }
1024
1025 final_token = cur_token;
1026
1027 while (1) {
1028 r = mailimap_unstrict_char_parse(fd, buffer, &cur_token, symbol);
1029 if (r == MAILIMAP_ERROR_PARSE)
1030 break;
1031 if (r != MAILIMAP_NO_ERROR) {
1032 res = r;
1033 goto free_list;
1034 }
1035
1036 r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun);
1037 if (r == MAILIMAP_ERROR_PARSE)
1038 break;
1039
1040 if (r != MAILIMAP_NO_ERROR) {
1041 res = r;
1042 goto free_list;
1043 }
1044
1045 r = clist_append(struct_list, value);
1046 if (r < 0) {
1047 destructor(value);
1048 res = MAILIMAP_ERROR_MEMORY;
1049 goto free_list;
1050 }
1051
1052 final_token = cur_token;
1053 }
1054
1055 * result = struct_list;
1056 * index = final_token;
1057
1058 return MAILIMAP_NO_ERROR;
1059
1060 free_list:
1061 clist_foreach(struct_list, (clist_func) destructor, NULL);
1062 clist_free(struct_list);
1063 err:
1064 return res;
1065}
1066
1067static int
1068mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer,
1069 size_t * index, clist ** result,
1070 mailimap_struct_parser * parser,
1071 mailimap_struct_destructor * destructor,
1072 size_t progr_rate,
1073 progress_function * progr_fun)
1074{
1075 return mailimap_struct_list_parse(fd, buffer, index, result,
1076 ' ', parser, destructor,
1077 progr_rate, progr_fun);
1078}
1079
1080
1081
1082static int
1083mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer,
1084 size_t * index, char ** result,
1085 int (* is_custom_char)(char))
1086{
1087 size_t begin;
1088 size_t end;
1089 char * gstr;
1090
1091 begin = * index;
1092
1093#ifdef UNSTRICT_SYNTAX
1094 mailimap_space_parse(fd, buffer, &begin);
1095#endif
1096
1097 end = begin;
1098
1099 while (is_custom_char(buffer->str[end]))
1100 end ++;
1101
1102 if (end != begin) {
1103 gstr = malloc(end - begin + 1);
1104 if (gstr == NULL)
1105 return MAILIMAP_ERROR_MEMORY;
1106
1107 strncpy(gstr, buffer->str + begin, end - begin);
1108 gstr[end - begin] = '\0';
1109
1110 * index = end;
1111 * result = gstr;
1112 return MAILIMAP_NO_ERROR;
1113 }
1114 else
1115 return MAILIMAP_ERROR_PARSE;
1116}
1117
1118
1119
1120static int
1121mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer,
1122 size_t * index,
1123 uint32_t ** result,
1124 size_t progr_rate,
1125 progress_function * progr_fun)
1126{
1127 uint32_t number;
1128 uint32_t * number_alloc;
1129 size_t cur_token;
1130 int r;
1131
1132 cur_token = * index;
1133
1134 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
1135 if (r != MAILIMAP_NO_ERROR)
1136 return r;
1137
1138 number_alloc = mailimap_number_alloc_new(number);
1139 if (number_alloc == NULL)
1140 return MAILIMAP_ERROR_MEMORY;
1141
1142 * index = cur_token;
1143 * result = number_alloc;
1144
1145 return MAILIMAP_NO_ERROR;
1146}
1147
1148
1149static int is_ctl(char ch)
1150{
1151 unsigned char uch = (unsigned char) ch;
1152
1153 return (uch <= 0x1F);
1154}
1155
1156static int is_char(char ch)
1157{
1158#ifdef UNSTRICT_SYNTAX
1159 return (ch != 0);
1160#else
1161 unsigned char uch = ch;
1162
1163 return (uch >= 0x01) && (uch <= 0x7f);
1164#endif
1165}
1166
1167static int is_alpha(char ch)
1168{
1169 return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z')));
1170}
1171
1172static int is_digit(char ch)
1173{
1174 return (ch >= '0') && (ch <= '9');
1175}
1176
1177static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer,
1178 size_t * index, int * result)
1179{
1180 size_t cur_token;
1181
1182 cur_token = * index;
1183
1184 if (is_digit(buffer->str[cur_token])) {
1185 * result = buffer->str[cur_token] - '0';
1186 cur_token ++;
1187 * index = cur_token;
1188 return MAILIMAP_NO_ERROR;
1189 }
1190 else
1191 return MAILIMAP_ERROR_PARSE;
1192}
1193
1194
1195/* ******************** parser **************************** */
1196
1197/*
1198 address = "(" addr-name SP addr-adl SP addr-mailbox SP
1199 addr-host ")"
1200*/
1201
1202static int mailimap_address_parse(mailstream * fd, MMAPString * buffer,
1203 size_t * index,
1204 struct mailimap_address ** result,
1205 size_t progr_rate,
1206 progress_function * progr_fun)
1207{
1208 size_t cur_token;
1209 char * addr_name;
1210 char * addr_adl;
1211 char * addr_mailbox;
1212 char * addr_host;
1213 struct mailimap_address * addr;
1214 int r;
1215 int res;
1216
1217 cur_token = * index;
1218
1219 addr_name = NULL;
1220 addr_adl = NULL;
1221 addr_mailbox = NULL;
1222 addr_host = NULL;
1223
1224 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1225 if (r != MAILIMAP_NO_ERROR) {
1226 res = r;
1227 goto err;
1228 }
1229
1230 r = mailimap_addr_name_parse(fd, buffer, &cur_token, &addr_name,
1231 progr_rate, progr_fun);
1232 if (r != MAILIMAP_NO_ERROR) {
1233 res = r;
1234 goto err;
1235 }
1236
1237 r = mailimap_space_parse(fd, buffer, &cur_token);
1238 if (r != MAILIMAP_NO_ERROR) {
1239 res = r;
1240 goto addr_name_free;
1241 }
1242
1243 r = mailimap_addr_adl_parse(fd, buffer, &cur_token, &addr_adl,
1244 progr_rate, progr_fun);
1245 if (r != MAILIMAP_NO_ERROR) {
1246 res = r;
1247 goto addr_name_free;
1248 }
1249
1250 r = mailimap_space_parse(fd, buffer, &cur_token);
1251 if (r != MAILIMAP_NO_ERROR) {
1252 res = r;
1253 goto addr_adl_free;
1254 }
1255
1256 r = mailimap_addr_mailbox_parse(fd, buffer, &cur_token, &addr_mailbox,
1257 progr_rate, progr_fun);
1258 if (r != MAILIMAP_NO_ERROR) {
1259 res = r;
1260 goto addr_adl_free;
1261 }
1262
1263 r = mailimap_space_parse(fd, buffer, &cur_token);
1264 if (r != MAILIMAP_NO_ERROR) {
1265 res = r;
1266 goto addr_mailbox_free;
1267 }
1268
1269 r = mailimap_addr_host_parse(fd, buffer, &cur_token, &addr_host,
1270 progr_rate, progr_fun);
1271 if (r != MAILIMAP_NO_ERROR) {
1272 res = r;
1273 goto addr_mailbox_free;
1274 }
1275
1276 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1277 if (r != MAILIMAP_NO_ERROR) {
1278 res = r;
1279 goto addr_host_free;
1280 }
1281
1282 addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host);
1283
1284 if (addr == NULL) {
1285 res = MAILIMAP_ERROR_MEMORY;
1286 goto addr_host_free;
1287 }
1288
1289 * result = addr;
1290 * index = cur_token;
1291
1292 return MAILIMAP_NO_ERROR;
1293
1294 addr_host_free:
1295 mailimap_addr_host_free(addr_host);
1296 addr_mailbox_free:
1297 mailimap_addr_mailbox_free(addr_mailbox);
1298 addr_adl_free:
1299 mailimap_addr_adl_free(addr_adl);
1300 addr_name_free:
1301 mailimap_addr_name_free(addr_name);
1302 err:
1303 return res;
1304}
1305
1306/*
1307 addr-adl = nstring
1308 ; Holds route from [RFC-822] route-addr if
1309 ; non-NIL
1310*/
1311
1312static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer,
1313 size_t * index, char ** result,
1314 size_t progr_rate,
1315 progress_function * progr_fun)
1316{
1317 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1318 progr_rate, progr_fun);
1319}
1320
1321/*
1322 addr-host = nstring
1323 ; NIL indicates [RFC-822] group syntax.
1324 ; Otherwise, holds [RFC-822] domain name
1325*/
1326
1327static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer,
1328 size_t * index, char ** result,
1329 size_t progr_rate,
1330 progress_function * progr_fun)
1331{
1332 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1333 progr_rate, progr_fun);
1334}
1335
1336/*
1337 addr-mailbox = nstring
1338 ; NIL indicates end of [RFC-822] group; if
1339 ; non-NIL and addr-host is NIL, holds
1340 ; [RFC-822] group name.
1341 ; Otherwise, holds [RFC-822] local-part
1342 ; after removing [RFC-822] quoting
1343 */
1344
1345static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer,
1346 size_t * index, char ** result,
1347 size_t progr_rate,
1348 progress_function * progr_fun)
1349{
1350 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1351 progr_rate, progr_fun);
1352}
1353
1354
1355/*
1356 addr-name = nstring
1357 ; If non-NIL, holds phrase from [RFC-822]
1358 ; mailbox after removing [RFC-822] quoting
1359*/
1360
1361static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer,
1362 size_t * index, char ** result,
1363 size_t progr_rate,
1364 progress_function * progr_fun)
1365{
1366 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
1367 progr_rate, progr_fun);
1368}
1369
1370
1371/*
1372 NOT IMPLEMENTED
1373 append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
1374 literal
1375*/
1376
1377/*
1378 astring = 1*ASTRING-CHAR / string
1379*/
1380
1381static int is_astring_char(char ch);
1382
1383static int
1384mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer,
1385 size_t * index, char ** result,
1386 size_t progr_rate,
1387 progress_function * progr_fun)
1388{
1389 return mailimap_custom_string_parse(fd, buffer, index, result,
1390 is_astring_char);
1391}
1392
1393static int
1394mailimap_astring_parse(mailstream * fd, MMAPString * buffer,
1395 size_t * index,
1396 char ** result,
1397 size_t progr_rate,
1398 progress_function * progr_fun)
1399{
1400 size_t cur_token;
1401 char * astring;
1402 int r;
1403
1404 cur_token = * index;
1405
1406 r = mailimap_atom_astring_parse(fd, buffer, &cur_token, &astring,
1407 progr_rate, progr_fun);
1408 switch (r) {
1409 case MAILIMAP_NO_ERROR:
1410 break;
1411
1412 case MAILIMAP_ERROR_PARSE:
1413 r = mailimap_string_parse(fd, buffer, &cur_token, &astring, NULL,
1414 progr_rate, progr_fun);
1415 if (r != MAILIMAP_NO_ERROR)
1416 return r;
1417 break;
1418
1419 default:
1420 return r;
1421 }
1422
1423 * result = astring;
1424 * index = cur_token;
1425
1426 return MAILIMAP_NO_ERROR;
1427}
1428
1429/*
1430 ASTRING-CHAR = ATOM-CHAR / resp-specials
1431*/
1432
1433static int is_atom_char(char ch);
1434static int is_resp_specials(char ch);
1435
1436static int is_astring_char(char ch)
1437{
1438 if (is_atom_char(ch))
1439 return TRUE;
1440 if (is_resp_specials(ch))
1441 return TRUE;
1442 return FALSE;
1443}
1444
1445/*
1446 atom = 1*ATOM-CHAR
1447*/
1448
1449static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer,
1450 size_t * index, char ** result,
1451 size_t progr_rate,
1452 progress_function * progr_fun)
1453{
1454 return mailimap_custom_string_parse(fd, buffer, index, result,
1455 is_atom_char);
1456}
1457
1458/*
1459 ATOM-CHAR = <any CHAR except atom-specials>
1460*/
1461
1462static int is_atom_specials(char ch);
1463
1464static int is_atom_char(char ch)
1465{
1466 if (is_atom_specials(ch))
1467 return FALSE;
1468
1469 return is_char(ch);
1470}
1471
1472/*
1473 atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
1474 quoted-specials / resp-specials
1475
1476no "}" because there is no need (Mark Crispin)
1477*/
1478
1479static int is_quoted_specials(char ch);
1480static int is_list_wildcards(char ch);
1481
1482static int is_atom_specials(char ch)
1483{
1484 switch (ch) {
1485 case '(':
1486 case ')':
1487 case '{':
1488 case ' ':
1489 return TRUE;
1490 };
1491 if (is_ctl(ch))
1492 return TRUE;
1493 if (is_list_wildcards(ch))
1494 return TRUE;
1495 if (is_resp_specials(ch))
1496 return TRUE;
1497
1498 return is_quoted_specials(ch);
1499}
1500
1501/*
1502 NOT IMPLEMENTED
1503 authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
1504*/
1505
1506/*
1507 auth-type = atom
1508 ; Defined by [SASL]
1509*/
1510
1511static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer,
1512 size_t * index, char ** result,
1513 size_t progr_rate,
1514 progress_function * progr_fun)
1515{
1516 return mailimap_atom_parse(fd, buffer, index, result,
1517 progr_rate, progr_fun);
1518}
1519
1520/*
1521 base64 = *(4base64-char) [base64-terminal]
1522*/
1523
1524static int is_base64_4char(char * str);
1525static int is_base64_terminal(char * str);
1526
1527static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer,
1528 size_t * index, char ** result,
1529 size_t progr_rate,
1530 progress_function * progr_fun)
1531{
1532 size_t begin;
1533 size_t end;
1534 char * gstr;
1535
1536 begin = * index;
1537 end = begin;
1538
1539 while (is_base64_4char(buffer->str + end))
1540 end += 4;
1541 if (is_base64_terminal(buffer->str + end))
1542 end += 4;
1543 else
1544 return MAILIMAP_ERROR_PARSE;
1545
1546 gstr = malloc(end - begin + 1);
1547 if (gstr == NULL)
1548 return MAILIMAP_ERROR_MEMORY;
1549 strncpy(gstr, buffer->str + begin, end - begin);
1550 gstr[end - begin] = '\0';
1551
1552 * result = gstr;
1553 * index = end;
1554
1555 return MAILIMAP_NO_ERROR;
1556}
1557
1558/*
1559 base64-char = ALPHA / DIGIT / "+" / "/"
1560 ; Case-sensitive
1561*/
1562
1563static int is_base64_char(char ch)
1564{
1565 return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/');
1566}
1567
1568static int is_base64_4char(char * str)
1569{
1570 size_t i;
1571
1572 for (i = 0 ; i < 4 ; i++)
1573 if (!is_base64_char(str[i]))
1574 return FALSE;
1575 return TRUE;
1576}
1577
1578/*
1579 base64-terminal = (2base64-char "==") / (3base64-char "=")
1580*/
1581
1582static int is_base64_terminal(char * str)
1583{
1584 if (str[0] == 0)
1585 return FALSE;
1586 if (str[1] == 0)
1587 return FALSE;
1588 if (str[2] == 0)
1589 return FALSE;
1590 if (str[3] == 0)
1591 return FALSE;
1592
1593 if (is_base64_char(str[0]) || is_base64_char(str[1])
1594 || str[2] == '=' || str[3] == '=')
1595 return TRUE;
1596 if (is_base64_char(str[0]) || is_base64_char(str[1])
1597 || is_base64_char(str[2]) || str[3] == '=')
1598 return TRUE;
1599 return FALSE;
1600}
1601
1602
1603/*
1604 body = "(" (body-type-1part / body-type-mpart) ")"
1605*/
1606
1607static int mailimap_body_parse(mailstream * fd, MMAPString * buffer,
1608 size_t * index,
1609 struct mailimap_body ** result,
1610 size_t progr_rate,
1611 progress_function * progr_fun)
1612{
1613 struct mailimap_body_type_1part * body_type_1part;
1614 struct mailimap_body_type_mpart * body_type_mpart;
1615 struct mailimap_body * body;
1616 size_t cur_token;
1617 int type;
1618 int r;
1619 int res;
1620
1621 cur_token = * index;
1622
1623 body_type_1part = NULL;
1624 body_type_mpart = NULL;
1625
1626 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1627 if (r != MAILIMAP_NO_ERROR) {
1628 res = r;
1629 goto err;
1630 }
1631
1632 type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */
1633
1634 r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part,
1635 progr_rate, progr_fun);
1636 if (r == MAILIMAP_NO_ERROR)
1637 type = MAILIMAP_BODY_1PART;
1638
1639 if (r == MAILIMAP_ERROR_PARSE) {
1640 r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token,
1641 &body_type_mpart,
1642 progr_rate, progr_fun);
1643
1644 if (r == MAILIMAP_NO_ERROR)
1645 type = MAILIMAP_BODY_MPART;
1646 }
1647
1648 if (r != MAILIMAP_NO_ERROR) {
1649 res = r;
1650 goto err;
1651 }
1652
1653 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1654 if (r != MAILIMAP_NO_ERROR) {
1655 res = r;
1656 goto free;
1657 }
1658
1659 body = mailimap_body_new(type, body_type_1part, body_type_mpart);
1660 if (body == NULL) {
1661 res = MAILIMAP_ERROR_MEMORY;
1662 goto free;
1663 }
1664
1665 * result = body;
1666 * index = cur_token;
1667
1668 return MAILIMAP_NO_ERROR;
1669
1670 free:
1671 if (body_type_1part)
1672 mailimap_body_type_1part_free(body_type_1part);
1673 if (body_type_mpart)
1674 mailimap_body_type_mpart_free(body_type_mpart);
1675 err:
1676 return res;
1677}
1678
1679/*
1680 body-extension = nstring / number /
1681 "(" body-extension *(SP body-extension) ")"
1682 ; Future expansion. Client implementations
1683 ; MUST accept body-extension fields. Server
1684 ; implementations MUST NOT generate
1685 ; body-extension fields except as defined by
1686 ; future standard or standards-track
1687 ; revisions of this specification.
1688*/
1689
1690/*
1691 "(" body-extension *(SP body-extension) ")"
1692*/
1693
1694static int
1695mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer,
1696 size_t * index,
1697 clist ** result,
1698 size_t progr_rate,
1699 progress_function * progr_fun)
1700{
1701 size_t cur_token;
1702 clist * list;
1703 int r;
1704 int res;
1705
1706 cur_token = * index;
1707
1708 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
1709 if (r != MAILIMAP_NO_ERROR) {
1710 res = r;
1711 goto err;
1712 }
1713
1714 r = mailimap_struct_spaced_list_parse(fd, buffer,
1715 &cur_token, &list,
1716 (mailimap_struct_parser * )
1717 mailimap_body_extension_parse,
1718 (mailimap_struct_destructor * )
1719 mailimap_body_extension_free,
1720 progr_rate, progr_fun);
1721 if (r != MAILIMAP_NO_ERROR) {
1722 res = r;
1723 goto err;
1724 }
1725
1726 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
1727 if (r != MAILIMAP_NO_ERROR) {
1728 res = r;
1729 goto free_list;
1730 }
1731
1732 * index = cur_token;
1733 * result = list;
1734
1735 return MAILIMAP_NO_ERROR;
1736
1737 free_list:
1738 clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL);
1739 clist_free(list);
1740 err:
1741 return res;
1742}
1743
1744/*
1745 body-extension = nstring / number /
1746 "(" body-extension *(SP body-extension) ")"
1747 ; Future expansion. Client implementations
1748 ; MUST accept body-extension fields. Server
1749 ; implementations MUST NOT generate
1750 ; body-extension fields except as defined by
1751 ; future standard or standards-track
1752 ; revisions of this specification.
1753*/
1754
1755static int
1756mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer,
1757 size_t * index,
1758 struct mailimap_body_extension ** result,
1759 size_t progr_rate,
1760 progress_function * progr_fun)
1761{
1762 size_t cur_token;
1763 uint32_t number;
1764 char * nstring;
1765 clist * body_extension_list;
1766 struct mailimap_body_extension * body_extension;
1767 int type;
1768 int r;
1769 int res;
1770
1771 cur_token = * index;
1772
1773 nstring = NULL;
1774 number = 0;
1775 body_extension_list = NULL;
1776 type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */
1777
1778 r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL,
1779 progr_rate, progr_fun);
1780 if (r == MAILIMAP_NO_ERROR)
1781 type = MAILIMAP_BODY_EXTENSION_NSTRING;
1782
1783 if (r == MAILIMAP_ERROR_PARSE) {
1784 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
1785
1786 if (r == MAILIMAP_NO_ERROR)
1787 type = MAILIMAP_BODY_EXTENSION_NUMBER;
1788 }
1789
1790 if (r == MAILIMAP_ERROR_PARSE) {
1791 r = mailimap_body_ext_list_parse(fd, buffer, &cur_token,
1792 &body_extension_list,
1793 progr_rate, progr_fun);
1794
1795 if (r == MAILIMAP_NO_ERROR)
1796 type = MAILIMAP_BODY_EXTENSION_LIST;
1797 }
1798
1799 if (r != MAILIMAP_NO_ERROR) {
1800 res = r;
1801 goto err;
1802 }
1803
1804 body_extension = mailimap_body_extension_new(type, nstring, number,
1805 body_extension_list);
1806
1807 if (body_extension == NULL) {
1808 res = MAILIMAP_ERROR_MEMORY;
1809 goto free;
1810 }
1811
1812 * result = body_extension;
1813 * index = cur_token;
1814
1815 return MAILIMAP_NO_ERROR;
1816
1817 free:
1818 if (nstring != NULL)
1819 mailimap_nstring_free(nstring);
1820 if (body_extension_list) {
1821 clist_foreach(body_extension_list,
1822 (clist_func) mailimap_body_extension_free,
1823 NULL);
1824 clist_free(body_extension_list);
1825 }
1826 err:
1827 return res;
1828}
1829
1830/*
1831 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1832 *(SP body-extension)]]
1833 ; MUST NOT be returned on non-extensible
1834 ; "BODY" fetch
1835*/
1836
1837/*
1838 *(SP body-extension)
1839*/
1840
1841static int
1842mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer,
1843 size_t * index,
1844 clist ** body_ext_list,
1845 size_t progr_rate,
1846 progress_function * progr_fun)
1847{
1848 size_t cur_token;
1849 int r;
1850
1851 cur_token = * index;
1852 * body_ext_list = NULL;
1853
1854 r = mailimap_space_parse(fd, buffer, &cur_token);
1855 if (r != MAILIMAP_NO_ERROR)
1856 return r;
1857
1858 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
1859 body_ext_list,
1860 (mailimap_struct_parser *)
1861 mailimap_body_extension_parse,
1862 (mailimap_struct_destructor *)
1863 mailimap_body_extension_free,
1864 progr_rate, progr_fun);
1865 if (r != MAILIMAP_NO_ERROR)
1866 return r;
1867
1868 * index = cur_token;
1869
1870 return MAILIMAP_NO_ERROR;
1871}
1872
1873
1874/*
1875 [SP body-fld-lang
1876 *(SP body-extension)]]
1877*/
1878
1879static int
1880mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer,
1881 size_t * index,
1882 struct mailimap_body_fld_lang ** fld_lang,
1883 clist ** body_ext_list,
1884 size_t progr_rate,
1885 progress_function * progr_fun)
1886{
1887 size_t cur_token;
1888 int r;
1889
1890 cur_token = * index;
1891 * fld_lang = NULL;
1892 * body_ext_list = NULL;
1893
1894 r = mailimap_space_parse(fd, buffer, &cur_token);
1895 if (r != MAILIMAP_NO_ERROR)
1896 return r;
1897
1898 r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang,
1899 progr_rate, progr_fun);
1900 if (r != MAILIMAP_NO_ERROR)
1901 return r;
1902
1903 r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token,
1904 body_ext_list, progr_rate, progr_fun);
1905 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1906 return r;
1907
1908 * index = cur_token;
1909
1910 return MAILIMAP_NO_ERROR;
1911}
1912
1913
1914/*
1915 SP body-fld-dsp [SP body-fld-lang
1916 *(SP body-extension)]]
1917*/
1918
1919static int
1920mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer,
1921 size_t * index,
1922 struct mailimap_body_fld_dsp ** fld_dsp,
1923 struct mailimap_body_fld_lang ** fld_lang,
1924 clist ** body_ext_list,
1925 size_t progr_rate,
1926 progress_function * progr_fun)
1927{
1928 size_t cur_token;
1929 int r;
1930
1931 cur_token = * index;
1932 * fld_dsp = NULL;
1933 * fld_lang = NULL;
1934 * body_ext_list = NULL;
1935
1936 r = mailimap_space_parse(fd, buffer, &cur_token);
1937 if (r != MAILIMAP_NO_ERROR)
1938 return r;
1939
1940 r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp,
1941 progr_rate, progr_fun);
1942 if (r != MAILIMAP_NO_ERROR)
1943 return r;
1944
1945 r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token,
1946 fld_lang, body_ext_list,
1947 progr_rate, progr_fun);
1948 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
1949 return r;
1950
1951 * index = cur_token;
1952
1953 return MAILIMAP_NO_ERROR;
1954}
1955
1956/*
1957 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1958 *(SP body-extension)]]
1959 ; MUST NOT be returned on non-extensible
1960 ; "BODY" fetch
1961*/
1962
1963static int
1964mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer,
1965 size_t * index,
1966 struct mailimap_body_ext_1part ** result,
1967 size_t progr_rate,
1968 progress_function * progr_fun)
1969{
1970 size_t cur_token;
1971
1972 char * fld_md5;
1973 struct mailimap_body_fld_dsp * fld_dsp;
1974 struct mailimap_body_fld_lang * fld_lang;
1975 clist * body_ext_list;
1976 int r;
1977 int res;
1978
1979 struct mailimap_body_ext_1part * ext_1part;
1980
1981 cur_token = * index;
1982
1983 fld_md5 = NULL;
1984 fld_dsp = NULL;
1985 fld_lang = NULL;
1986 body_ext_list = NULL;
1987
1988 r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5,
1989 progr_rate, progr_fun);
1990 if (r != MAILIMAP_NO_ERROR) {
1991 res = r;
1992 goto err;
1993 }
1994
1995 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
1996 &fld_dsp,
1997 &fld_lang,
1998 &body_ext_list,
1999 progr_rate, progr_fun);
2000 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2001 res = r;
2002 goto free;
2003 }
2004
2005 ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang,
2006 body_ext_list);
2007
2008 if (ext_1part == NULL) {
2009 res = MAILIMAP_ERROR_MEMORY;
2010 goto free;
2011 }
2012
2013 * result = ext_1part;
2014 * index = cur_token;
2015
2016 return MAILIMAP_NO_ERROR;
2017
2018 free:
2019 if (body_ext_list) {
2020 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2021 NULL);
2022 clist_free(body_ext_list);
2023 }
2024 if (fld_lang)
2025 mailimap_body_fld_lang_free(fld_lang);
2026 if (fld_dsp)
2027 mailimap_body_fld_dsp_free(fld_dsp);
2028 mailimap_body_fld_md5_free(fld_md5);
2029 err:
2030 return res;
2031}
2032
2033
2034/*
2035 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
2036 *(SP body-extension)]]
2037 ; MUST NOT be returned on non-extensible
2038 ; "BODY" fetch
2039*/
2040
2041static int
2042mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer,
2043 size_t * index,
2044 struct mailimap_body_ext_mpart ** result,
2045 size_t progr_rate,
2046 progress_function * progr_fun)
2047{
2048 size_t cur_token;
2049
2050 struct mailimap_body_fld_dsp * fld_dsp;
2051 struct mailimap_body_fld_lang * fld_lang;
2052 struct mailimap_body_fld_param * fld_param;
2053 clist * body_ext_list;
2054
2055 struct mailimap_body_ext_mpart * ext_mpart;
2056 int r;
2057 int res;
2058
2059 cur_token = * index;
2060
2061 fld_param = NULL;
2062 fld_dsp = NULL;
2063 fld_lang = NULL;
2064 body_ext_list = NULL;
2065
2066 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param,
2067 progr_rate, progr_fun);
2068 if (r != MAILIMAP_NO_ERROR) {
2069 res = r;
2070 goto err;
2071 }
2072
2073 r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token,
2074 &fld_dsp,
2075 &fld_lang,
2076 &body_ext_list,
2077 progr_rate, progr_fun);
2078 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
2079 res = r;
2080 goto free;
2081 }
2082
2083 ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang,
2084 body_ext_list);
2085 if (ext_mpart == NULL) {
2086 res = MAILIMAP_ERROR_MEMORY;
2087 goto free;
2088 }
2089
2090 * result = ext_mpart;
2091 * index = cur_token;
2092
2093 return MAILIMAP_NO_ERROR;
2094
2095 free:
2096 if (body_ext_list) {
2097 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
2098 NULL);
2099 clist_free(body_ext_list);
2100 }
2101 if (fld_lang)
2102 mailimap_body_fld_lang_free(fld_lang);
2103 if (fld_dsp)
2104 mailimap_body_fld_dsp_free(fld_dsp);
2105 if (fld_param != NULL)
2106 mailimap_body_fld_param_free(fld_param);
2107 err:
2108 return res;
2109}
2110
2111/*
2112 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
2113 body-fld-enc SP body-fld-octets
2114*/
2115
2116static int
2117mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer,
2118 size_t * index,
2119 struct mailimap_body_fields ** result,
2120 size_t progr_rate,
2121 progress_function * progr_fun)
2122{
2123 struct mailimap_body_fields * body_fields;
2124 size_t cur_token;
2125 struct mailimap_body_fld_param * body_fld_param;
2126 char * body_fld_id;
2127 char * body_fld_desc;
2128 struct mailimap_body_fld_enc * body_fld_enc;
2129 uint32_t body_fld_octets;
2130 int r;
2131 int res;
2132
2133 body_fld_param = NULL;
2134 body_fld_id = NULL;
2135 body_fld_desc = NULL;
2136 body_fld_enc = NULL;
2137 body_fld_octets = 0;
2138
2139 cur_token = * index;
2140
2141 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param,
2142 progr_rate, progr_fun);
2143 if (r != MAILIMAP_NO_ERROR) {
2144 res = r;
2145 goto err;
2146 }
2147
2148 r = mailimap_space_parse(fd, buffer, &cur_token);
2149 if (r != MAILIMAP_NO_ERROR) {
2150 res = r;
2151 goto fld_param_free;
2152 }
2153
2154 r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id,
2155 progr_rate, progr_fun);
2156 if (r != MAILIMAP_NO_ERROR) {
2157 res = r;
2158 goto fld_param_free;
2159 }
2160
2161 r = mailimap_space_parse(fd, buffer, &cur_token);
2162 if (r != MAILIMAP_NO_ERROR) {
2163 res = r;
2164 goto fld_id_free;
2165 }
2166
2167 r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc,
2168 progr_rate, progr_fun);
2169 if (r != MAILIMAP_NO_ERROR) {
2170 res = r;
2171 goto fld_id_free;
2172 }
2173
2174 r = mailimap_space_parse(fd, buffer, &cur_token);
2175 if (r != MAILIMAP_NO_ERROR) {
2176 res = r;
2177 goto fld_desc_free;
2178 }
2179
2180 r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc,
2181 progr_rate, progr_fun);
2182 if (r != MAILIMAP_NO_ERROR) {
2183 res = r;
2184 goto fld_desc_free;
2185 }
2186
2187 r = mailimap_space_parse(fd, buffer, &cur_token);
2188 if (r != MAILIMAP_NO_ERROR) {
2189 res = r;
2190 goto fld_enc_free;
2191 }
2192
2193 r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token,
2194 &body_fld_octets);
2195 if (r != MAILIMAP_NO_ERROR) {
2196 res = r;
2197 goto fld_enc_free;
2198 }
2199
2200 body_fields = mailimap_body_fields_new(body_fld_param,
2201 body_fld_id,
2202 body_fld_desc,
2203 body_fld_enc,
2204 body_fld_octets);
2205 if (body_fields == NULL) {
2206 res = MAILIMAP_ERROR_MEMORY;
2207 goto fld_enc_free;
2208 }
2209
2210 * result = body_fields;
2211 * index = cur_token;
2212
2213 return MAILIMAP_NO_ERROR;
2214
2215 fld_enc_free:
2216 mailimap_body_fld_enc_free(body_fld_enc);
2217 fld_desc_free:
2218 mailimap_body_fld_desc_free(body_fld_desc);
2219 fld_id_free:
2220 mailimap_body_fld_id_free(body_fld_id);
2221 fld_param_free:
2222 if (body_fld_param != NULL)
2223 mailimap_body_fld_param_free(body_fld_param);
2224 err:
2225 return res;
2226}
2227
2228/*
2229 body-fld-desc = nstring
2230*/
2231
2232static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer,
2233 size_t * index, char ** result,
2234 size_t progr_rate,
2235 progress_function * progr_fun)
2236{
2237 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2238 progr_rate, progr_fun);
2239}
2240
2241/*
2242 body-fld-dsp = "(" string SP body-fld-param ")" / nil
2243*/
2244
2245static int
2246mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer,
2247 size_t * index,
2248 struct mailimap_body_fld_dsp ** result,
2249 size_t progr_rate,
2250 progress_function * progr_fun)
2251{
2252 size_t cur_token;
2253 char * name;
2254 struct mailimap_body_fld_param * body_fld_param;
2255 struct mailimap_body_fld_dsp * body_fld_dsp;
2256 int res;
2257 int r;
2258
2259 cur_token = * index;
2260 name = NULL;
2261 body_fld_param = NULL;
2262
2263 r = mailimap_nil_parse(fd, buffer, &cur_token);
2264 if (r == MAILIMAP_NO_ERROR) {
2265 * result = NULL;
2266 * index = cur_token;
2267 return MAILIMAP_NO_ERROR;
2268 }
2269
2270 if (r != MAILIMAP_ERROR_PARSE) {
2271 res = r;
2272 goto err;
2273 }
2274
2275 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2276 if (r != MAILIMAP_NO_ERROR) {
2277 res = r;
2278 goto err;
2279 }
2280
2281 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2282 progr_rate, progr_fun);
2283 if (r != MAILIMAP_NO_ERROR) {
2284 res = r;
2285 goto err;
2286 }
2287
2288 r = mailimap_space_parse(fd, buffer, &cur_token);
2289 if (r != MAILIMAP_NO_ERROR) {
2290 res = r;
2291 goto string_free;
2292 }
2293
2294 r = mailimap_body_fld_param_parse(fd, buffer, &cur_token,
2295 &body_fld_param,
2296 progr_rate, progr_fun);
2297 if (r != MAILIMAP_NO_ERROR) {
2298 res = r;
2299 goto string_free;
2300 }
2301
2302 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2303 if (r != MAILIMAP_NO_ERROR) {
2304 res = r;
2305 goto string_free;
2306 }
2307
2308 body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param);
2309 if (body_fld_dsp == NULL) {
2310 res = MAILIMAP_ERROR_MEMORY;
2311 goto fld_param_free;
2312 }
2313
2314 * index = cur_token;
2315 * result = body_fld_dsp;
2316
2317 return MAILIMAP_NO_ERROR;
2318
2319 fld_param_free:
2320 if (body_fld_param != NULL)
2321 mailimap_body_fld_param_free(body_fld_param);
2322 string_free:
2323 mailimap_string_free(name);
2324 err:
2325 return res;
2326}
2327
2328/*
2329 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
2330 "QUOTED-PRINTABLE") DQUOTE) / string
2331*/
2332
2333static inline int
2334mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer,
2335 size_t * index,
2336 int * result,
2337 size_t progr_rate,
2338 progress_function * progr_fun)
2339{
2340 size_t cur_token;
2341 int type;
2342 int r;
2343 int res;
2344
2345 cur_token = * index;
2346
2347 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2348 if (r != MAILIMAP_NO_ERROR) {
2349 res = r;
2350 goto err;
2351 }
2352
2353 type = mailimap_encoding_get_token_value(fd, buffer, &cur_token);
2354
2355 if (type == -1) {
2356 res = MAILIMAP_ERROR_PARSE;
2357 goto err;
2358 }
2359
2360 r = mailimap_dquote_parse(fd, buffer, &cur_token);
2361 if (r != MAILIMAP_NO_ERROR) {
2362 res = r;
2363 goto err;
2364 }
2365
2366 * result = type;
2367 * index = cur_token;
2368
2369 return MAILIMAP_NO_ERROR;
2370
2371 err:
2372 return res;
2373}
2374
2375static int
2376mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer,
2377 size_t * index,
2378 struct mailimap_body_fld_enc ** result,
2379 size_t progr_rate,
2380 progress_function * progr_fun)
2381{
2382 size_t cur_token;
2383 int type;
2384 char * value;
2385 struct mailimap_body_fld_enc * body_fld_enc;
2386 int r;
2387 int res;
2388
2389 cur_token = * index;
2390
2391 r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token,
2392 &type, progr_rate, progr_fun);
2393 if (r == MAILIMAP_NO_ERROR) {
2394 value = NULL;
2395 }
2396 else if (r == MAILIMAP_ERROR_PARSE) {
2397 type = MAILIMAP_BODY_FLD_ENC_OTHER;
2398
2399 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2400 progr_rate, progr_fun);
2401 if (r != MAILIMAP_NO_ERROR) {
2402 res = r;
2403 goto err;
2404 }
2405 }
2406 else {
2407 res = r;
2408 goto err;
2409 }
2410
2411 body_fld_enc = mailimap_body_fld_enc_new(type, value);
2412 if (body_fld_enc == NULL) {
2413 res = MAILIMAP_ERROR_MEMORY;
2414 goto value_free;
2415 }
2416
2417 * result = body_fld_enc;
2418 * index = cur_token;
2419
2420 return MAILIMAP_NO_ERROR;
2421
2422 value_free:
2423 if (value)
2424 mailimap_string_free(value);
2425 err:
2426 return res;
2427}
2428
2429/*
2430 body-fld-id = nstring
2431*/
2432
2433static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer,
2434 size_t * index, char ** result,
2435 size_t progr_rate,
2436 progress_function * progr_fun)
2437{
2438 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2439 progr_rate, progr_fun);
2440}
2441
2442
2443/*
2444 body-fld-lang = nstring / "(" string *(SP string) ")"
2445*/
2446
2447/*
2448"(" string *(SP string) ")"
2449*/
2450
2451static int
2452mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer,
2453 size_t * index, clist ** result,
2454 size_t progr_rate,
2455 progress_function * progr_fun)
2456{
2457 size_t cur_token;
2458 clist * list;
2459 int r;
2460 int res;
2461
2462 cur_token = * index;
2463
2464 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2465 if (r != MAILIMAP_NO_ERROR) {
2466 res = r;
2467 goto err;
2468 }
2469
2470 list = clist_new();
2471 if (list == NULL) {
2472 res = MAILIMAP_ERROR_MEMORY;
2473 goto err;
2474 }
2475
2476 while (1) {
2477 char * elt;
2478
2479 r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL,
2480 progr_rate, progr_fun);
2481 if (r != MAILIMAP_ERROR_PARSE)
2482 break;
2483 else if (r == MAILIMAP_NO_ERROR) {
2484 r = clist_append(list, elt);
2485 if (r < 0) {
2486 mailimap_string_free(elt);
2487 res = r;
2488 goto list_free;
2489 }
2490 }
2491 else {
2492 res = r;
2493 goto list_free;
2494 }
2495 }
2496
2497 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2498 if (r != MAILIMAP_NO_ERROR) {
2499 res = r;
2500 goto list_free;
2501 }
2502
2503 * index = cur_token;
2504 * result = list;
2505
2506 return MAILIMAP_NO_ERROR;
2507
2508 list_free:
2509 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2510 clist_free(list);
2511 err:
2512 return res;
2513}
2514
2515/*
2516 body-fld-lang = nstring / "(" string *(SP string) ")"
2517*/
2518
2519static int
2520mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer,
2521 size_t * index,
2522 struct mailimap_body_fld_lang ** result,
2523 size_t progr_rate,
2524 progress_function * progr_fun)
2525{
2526 char * value;
2527 clist * list;
2528 struct mailimap_body_fld_lang * fld_lang;
2529 int type;
2530 int r;
2531 int res;
2532
2533 size_t cur_token;
2534
2535 cur_token = * index;
2536
2537 value = NULL;
2538 list = NULL;
2539 type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */
2540
2541 r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL,
2542 progr_rate, progr_fun);
2543 if (r == MAILIMAP_NO_ERROR)
2544 type = MAILIMAP_BODY_FLD_LANG_SINGLE;
2545
2546 if (r == MAILIMAP_ERROR_PARSE) {
2547 r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list,
2548 progr_rate, progr_fun);
2549 if (r == MAILIMAP_NO_ERROR)
2550 type = MAILIMAP_BODY_FLD_LANG_LIST;
2551 }
2552
2553 if (r != MAILIMAP_NO_ERROR) {
2554 res = r;
2555 goto err;
2556 }
2557
2558 fld_lang = mailimap_body_fld_lang_new(type, value, list);
2559 if (fld_lang == NULL) {
2560 res = MAILIMAP_ERROR_MEMORY;
2561 goto free;
2562 }
2563
2564 * index = cur_token;
2565 * result = fld_lang;
2566
2567 return MAILIMAP_NO_ERROR;
2568
2569 free:
2570 if (value)
2571 mailimap_nstring_free(value);
2572 if (list) {
2573 clist_foreach(list, (clist_func) mailimap_string_free, NULL);
2574 clist_free(list);
2575 }
2576 err:
2577 return res;
2578}
2579
2580/*
2581 body-fld-lines = number
2582*/
2583
2584static int mailimap_body_fld_lines_parse(mailstream * fd,
2585 MMAPString * buffer, size_t * index,
2586 uint32_t * result)
2587{
2588 return mailimap_number_parse(fd, buffer, index, result);
2589}
2590
2591/*
2592 body-fld-md5 = nstring
2593*/
2594
2595static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer,
2596 size_t * index, char ** result,
2597 size_t progr_rate,
2598 progress_function * progr_fun)
2599{
2600 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
2601 progr_rate, progr_fun);
2602}
2603
2604/*
2605 body-fld-octets = number
2606*/
2607
2608static int mailimap_body_fld_octets_parse(mailstream * fd,
2609 MMAPString * buffer, size_t * index,
2610 uint32_t * result)
2611{
2612 return mailimap_number_parse(fd, buffer, index, result);
2613}
2614
2615/*
2616 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2617*/
2618
2619/*
2620 string SP string
2621*/
2622
2623static int
2624mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer,
2625 size_t * index,
2626 struct mailimap_single_body_fld_param **
2627 result,
2628 size_t progr_rate,
2629 progress_function * progr_fun)
2630{
2631 struct mailimap_single_body_fld_param * param;
2632 char * name;
2633 char * value;
2634 size_t cur_token;
2635 int r;
2636 int res;
2637
2638 cur_token = * index;
2639
2640 name = NULL;
2641 value = NULL;
2642
2643 r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL,
2644 progr_rate, progr_fun);
2645 if (r != MAILIMAP_NO_ERROR) {
2646 res = r;
2647 goto err;
2648 }
2649
2650 r = mailimap_space_parse(fd, buffer, &cur_token);
2651 if (r != MAILIMAP_NO_ERROR) {
2652 res = r;
2653 goto free_name;
2654 }
2655
2656 r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL,
2657 progr_rate, progr_fun);
2658 if (r != MAILIMAP_NO_ERROR) {
2659 res = r;
2660 goto free_name;
2661 }
2662
2663 param = mailimap_single_body_fld_param_new(name, value);
2664 if (param == NULL) {
2665 res = MAILIMAP_ERROR_MEMORY;
2666 goto free_value;
2667 }
2668
2669 * result = param;
2670 * index = cur_token;
2671
2672 return MAILIMAP_NO_ERROR;
2673
2674 free_value:
2675 mailimap_string_free(name);
2676 free_name:
2677 mailimap_string_free(value);
2678 err:
2679 return res;
2680}
2681
2682/*
2683 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
2684*/
2685
2686static int
2687mailimap_body_fld_param_parse(mailstream * fd,
2688 MMAPString * buffer, size_t * index,
2689 struct mailimap_body_fld_param ** result,
2690 size_t progr_rate,
2691 progress_function * progr_fun)
2692{
2693 size_t cur_token;
2694 clist * param_list;
2695 struct mailimap_body_fld_param * fld_param;
2696 int r;
2697 int res;
2698
2699 param_list = NULL;
2700 cur_token = * index;
2701
2702 r = mailimap_nil_parse(fd, buffer, &cur_token);
2703 if (r == MAILIMAP_NO_ERROR) {
2704 * result = NULL;
2705 * index = cur_token;
2706 return MAILIMAP_NO_ERROR;
2707 }
2708
2709 if (r != MAILIMAP_ERROR_PARSE) {
2710 res = r;
2711 goto err;
2712 }
2713
2714 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
2715 if (r != MAILIMAP_NO_ERROR) {
2716 res = r;
2717 goto err;
2718 }
2719
2720 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &param_list,
2721 (mailimap_struct_parser *)
2722 mailimap_single_body_fld_param_parse,
2723 (mailimap_struct_destructor *)
2724 mailimap_single_body_fld_param_free,
2725 progr_rate, progr_fun);
2726 if (r != MAILIMAP_NO_ERROR) {
2727 res = r;
2728 goto err;
2729 }
2730
2731 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
2732 if (r != MAILIMAP_NO_ERROR) {
2733 res = r;
2734 goto free;
2735 }
2736
2737 fld_param = mailimap_body_fld_param_new(param_list);
2738 if (fld_param == NULL) {
2739 res = MAILIMAP_ERROR_MEMORY;
2740 goto free;
2741 }
2742
2743 * index = cur_token;
2744 * result = fld_param;
2745
2746 return MAILIMAP_NO_ERROR;
2747
2748 free:
2749 clist_foreach(param_list,
2750 (clist_func) mailimap_single_body_fld_param_free,
2751 NULL);
2752 clist_free(param_list);
2753 err:
2754 return res;
2755}
2756
2757/*
2758 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
2759 [SP body-ext-1part]
2760*/
2761
2762static int
2763mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer,
2764 size_t * index,
2765 struct mailimap_body_type_1part ** result,
2766 size_t progr_rate,
2767 progress_function * progr_fun)
2768{
2769 size_t cur_token;
2770 struct mailimap_body_type_1part * body_type_1part;
2771 struct mailimap_body_type_basic * body_type_basic;
2772 struct mailimap_body_type_msg * body_type_msg;
2773 struct mailimap_body_type_text * body_type_text;
2774 struct mailimap_body_ext_1part * body_ext_1part;
2775 int type;
2776 size_t final_token;
2777 int r;
2778 int res;
2779
2780 cur_token = * index;
2781
2782 body_type_basic = NULL;
2783 body_type_msg = NULL;
2784 body_type_text = NULL;
2785 body_ext_1part = NULL;
2786
2787 type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */
2788
2789 r = mailimap_body_type_msg_parse(fd, buffer, &cur_token,
2790 &body_type_msg,
2791 progr_rate, progr_fun);
2792 if (r == MAILIMAP_NO_ERROR)
2793 type = MAILIMAP_BODY_TYPE_1PART_MSG;
2794
2795 if (r == MAILIMAP_ERROR_PARSE) {
2796 r = mailimap_body_type_text_parse(fd, buffer, &cur_token,
2797 &body_type_text,
2798 progr_rate, progr_fun);
2799 if (r == MAILIMAP_NO_ERROR)
2800 type = MAILIMAP_BODY_TYPE_1PART_TEXT;
2801 }
2802
2803 if (r == MAILIMAP_ERROR_PARSE) {
2804 r = mailimap_body_type_basic_parse(fd, buffer, &cur_token,
2805 &body_type_basic,
2806 progr_rate, progr_fun);
2807 if (r == MAILIMAP_NO_ERROR)
2808 type = MAILIMAP_BODY_TYPE_1PART_BASIC;
2809 }
2810
2811 if (r != MAILIMAP_NO_ERROR) {
2812 res = r;
2813 goto err;
2814 }
2815
2816 final_token = cur_token;
2817 body_ext_1part = NULL;
2818
2819 r = mailimap_space_parse(fd, buffer, &cur_token);
2820
2821 if (r == MAILIMAP_NO_ERROR) {
2822 r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part,
2823 progr_rate, progr_fun);
2824 if (r == MAILIMAP_NO_ERROR)
2825 final_token = cur_token;
2826 else if (r == MAILIMAP_ERROR_PARSE) {
2827 /* do nothing */
2828 }
2829 else {
2830 res = r;
2831 goto free;
2832 }
2833 }
2834 else if (r == MAILIMAP_ERROR_PARSE) {
2835 /* do nothing */
2836 }
2837 else {
2838 res = r;
2839 goto free;
2840 }
2841
2842 body_type_1part = mailimap_body_type_1part_new(type, body_type_basic,
2843 body_type_msg, body_type_text,
2844 body_ext_1part);
2845 if (body_type_1part == NULL) {
2846 res = MAILIMAP_ERROR_MEMORY;
2847 goto free;
2848 }
2849
2850 * index = final_token;
2851 * result = body_type_1part;
2852
2853 return MAILIMAP_NO_ERROR;
2854
2855 free:
2856 if (body_type_basic)
2857 mailimap_body_type_basic_free(body_type_basic);
2858 if (body_type_msg)
2859 mailimap_body_type_msg_free(body_type_msg);
2860 if (body_type_text)
2861 mailimap_body_type_text_free(body_type_text);
2862 if (body_ext_1part)
2863 mailimap_body_ext_1part_free(body_ext_1part);
2864 err:
2865 return res;
2866}
2867
2868/*
2869 body-type-basic = media-basic SP body-fields
2870 ; MESSAGE subtype MUST NOT be "RFC822"
2871*/
2872
2873static int
2874mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer,
2875 size_t * index,
2876 struct mailimap_body_type_basic ** result,
2877 size_t progr_rate,
2878 progress_function * progr_fun)
2879{
2880 size_t cur_token;
2881 struct mailimap_body_type_basic * body_type_basic;
2882 struct mailimap_media_basic * media_basic;
2883 struct mailimap_body_fields * body_fields;
2884 int r;
2885 int res;
2886
2887 cur_token = * index;
2888
2889 media_basic = NULL;
2890 body_fields = NULL;
2891
2892 r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic,
2893 progr_rate, progr_fun);
2894 if (r != MAILIMAP_NO_ERROR) {
2895 res = r;
2896 goto err;
2897 }
2898
2899 r = mailimap_space_parse(fd, buffer, &cur_token);
2900 if (r != MAILIMAP_NO_ERROR) {
2901 res = r;
2902 goto free_media_basic;
2903 }
2904
2905 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
2906 progr_rate, progr_fun);
2907 if (r != MAILIMAP_NO_ERROR) {
2908 res = r;
2909 goto free_media_basic;
2910 }
2911
2912 body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields);
2913 if (body_type_basic == NULL) {
2914 res = MAILIMAP_ERROR_MEMORY;
2915 goto free_body_fields;
2916 }
2917
2918 * index = cur_token;
2919 * result = body_type_basic;
2920
2921 return MAILIMAP_NO_ERROR;
2922
2923 free_body_fields:
2924 mailimap_body_fields_free(body_fields);
2925 free_media_basic:
2926 mailimap_media_basic_free(media_basic);
2927 err:
2928 return res;
2929}
2930
2931/*
2932 body-type-mpart = 1*body SP media-subtype
2933 [SP body-ext-mpart]
2934*/
2935
2936static int
2937mailimap_body_type_mpart_parse(mailstream * fd,
2938 MMAPString * buffer,
2939 size_t * index,
2940 struct mailimap_body_type_mpart ** result,
2941 size_t progr_rate,
2942 progress_function * progr_fun)
2943{
2944 struct mailimap_body_type_mpart * body_type_mpart;
2945 clist * body_list;
2946 size_t cur_token;
2947 size_t final_token;
2948 char * media_subtype;
2949 struct mailimap_body_ext_mpart * body_ext_mpart;
2950 int r;
2951 int res;
2952
2953 cur_token = * index;
2954
2955 body_list = NULL;
2956 media_subtype = NULL;
2957 body_ext_mpart = NULL;
2958
2959 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token,
2960 &body_list,
2961 (mailimap_struct_parser *)
2962 mailimap_body_parse,
2963 (mailimap_struct_destructor *)
2964 mailimap_body_free,
2965 progr_rate, progr_fun);
2966 if (r != MAILIMAP_NO_ERROR) {
2967 res = r;
2968 goto err;
2969 }
2970
2971 r = mailimap_space_parse(fd, buffer, &cur_token);
2972 if (r != MAILIMAP_NO_ERROR) {
2973 res = r;
2974 goto free_body_list;
2975 }
2976
2977 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype,
2978 progr_rate, progr_fun);
2979 if (r != MAILIMAP_NO_ERROR) {
2980 res = r;
2981 goto free_body_list;
2982 }
2983
2984 final_token = cur_token;
2985
2986 body_ext_mpart = NULL;
2987
2988 r = mailimap_space_parse(fd, buffer, &cur_token);
2989 if (r == MAILIMAP_NO_ERROR) {
2990 r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart,
2991 progr_rate, progr_fun);
2992 if (r == MAILIMAP_NO_ERROR)
2993 final_token = cur_token;
2994 else if (r == MAILIMAP_ERROR_PARSE) {
2995 /* do nothing */
2996 }
2997 else {
2998 res = r;
2999 goto free_body_list;
3000 }
3001 }
3002 else if (r == MAILIMAP_ERROR_PARSE) {
3003 /* do nothing */
3004 }
3005 else {
3006 res = r;
3007 goto free_body_list;
3008 }
3009
3010 body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype,
3011 body_ext_mpart);
3012 if (body_type_mpart == NULL) {
3013 res = MAILIMAP_ERROR_MEMORY;
3014 goto free_body_ext_mpart;
3015 }
3016
3017 * result = body_type_mpart;
3018 * index = final_token;
3019
3020 return MAILIMAP_NO_ERROR;
3021
3022 free_body_ext_mpart:
3023 if (body_ext_mpart)
3024 mailimap_body_ext_mpart_free(body_ext_mpart);
3025 mailimap_media_subtype_free(media_subtype);
3026 free_body_list:
3027 clist_foreach(body_list, (clist_func) mailimap_body_free, NULL);
3028 clist_free(body_list);
3029 err:
3030 return res;
3031}
3032
3033/*
3034 body-type-msg = media-message SP body-fields SP envelope
3035 SP body SP body-fld-lines
3036*/
3037
3038static int
3039mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer,
3040 size_t * index,
3041 struct mailimap_body_type_msg ** result,
3042 size_t progr_rate,
3043 progress_function * progr_fun)
3044{
3045 struct mailimap_body_fields * body_fields;
3046 struct mailimap_envelope * envelope;
3047 struct mailimap_body * body;
3048 uint32_t body_fld_lines;
3049 struct mailimap_body_type_msg * body_type_msg;
3050 size_t cur_token;
3051 int r;
3052 int res;
3053
3054 cur_token = * index;
3055
3056 body_fields = NULL;
3057 envelope = NULL;
3058 body = NULL;
3059 body_fld_lines = 0;
3060
3061 r = mailimap_media_message_parse(fd, buffer, &cur_token);
3062 if (r != MAILIMAP_NO_ERROR) {
3063 res = r;
3064 goto err;
3065 }
3066
3067 r = mailimap_space_parse(fd, buffer, &cur_token);
3068 if (r != MAILIMAP_NO_ERROR) {
3069 res = r;
3070 goto err;
3071 }
3072
3073 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
3074 progr_rate, progr_fun);
3075 if (r != MAILIMAP_NO_ERROR) {
3076 res = r;
3077 goto err;
3078 }
3079
3080 r = mailimap_space_parse(fd, buffer, &cur_token);
3081 if (r != MAILIMAP_NO_ERROR) {
3082 res = r;
3083 goto body_fields;
3084 }
3085
3086 r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope,
3087 progr_rate, progr_fun);
3088 if (r != MAILIMAP_NO_ERROR) {
3089 res = r;
3090 goto body_fields;
3091 }
3092
3093 r = mailimap_space_parse(fd, buffer, &cur_token);
3094 if (r != MAILIMAP_NO_ERROR) {
3095 res = r;
3096 goto envelope;
3097 }
3098
3099 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
3100 progr_rate, progr_fun);
3101 if (r != MAILIMAP_NO_ERROR) {
3102 res = r;
3103 goto envelope;
3104 }
3105
3106 r = mailimap_space_parse(fd, buffer, &cur_token);
3107 if (r != MAILIMAP_NO_ERROR) {
3108 res = r;
3109 goto body;
3110 }
3111
3112 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token,
3113 &body_fld_lines);
3114 if (r != MAILIMAP_NO_ERROR) {
3115 res = r;
3116 goto body;
3117 }
3118
3119 body_type_msg = mailimap_body_type_msg_new(body_fields, envelope,
3120 body, body_fld_lines);
3121 if (body_type_msg == NULL) {
3122 res = MAILIMAP_ERROR_MEMORY;
3123 goto body;
3124 }
3125
3126 * result = body_type_msg;
3127 * index = cur_token;
3128
3129 return MAILIMAP_NO_ERROR;
3130
3131 body:
3132 mailimap_body_free(body);
3133 envelope:
3134 mailimap_envelope_free(envelope);
3135 body_fields:
3136 mailimap_body_fields_free(body_fields);
3137 err:
3138 return res;
3139}
3140
3141/*
3142 body-type-text = media-text SP body-fields SP body-fld-lines
3143*/
3144
3145static int
3146mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer,
3147 size_t * index,
3148 struct mailimap_body_type_text **
3149 result,
3150 size_t progr_rate,
3151 progress_function * progr_fun)
3152{
3153 char * media_text;
3154 struct mailimap_body_fields * body_fields;
3155 uint32_t body_fld_lines;
3156 struct mailimap_body_type_text * body_type_text;
3157 size_t cur_token;
3158 int r;
3159 int res;
3160
3161 media_text = NULL;
3162 body_fields = NULL;
3163 body_fld_lines = 0;
3164
3165 cur_token = * index;
3166
3167 r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text,
3168 progr_rate, progr_fun);
3169 if (r != MAILIMAP_NO_ERROR) {
3170 res = r;
3171 goto err;
3172 }
3173
3174 r = mailimap_space_parse(fd, buffer, &cur_token);
3175 if (r != MAILIMAP_NO_ERROR) {
3176 res = r;
3177 goto free_media_text;
3178 }
3179
3180 r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields,
3181 progr_rate, progr_fun);
3182 if (r != MAILIMAP_NO_ERROR) {
3183 res = r;
3184 goto free_media_text;
3185 }
3186
3187 r = mailimap_space_parse(fd, buffer, &cur_token);
3188 if (r != MAILIMAP_NO_ERROR) {
3189 res = r;
3190 goto free_body_fields;
3191 }
3192
3193 r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines);
3194 if (r != MAILIMAP_NO_ERROR) {
3195 res = r;
3196 goto free_body_fields;
3197 }
3198
3199 body_type_text = mailimap_body_type_text_new(media_text, body_fields,
3200 body_fld_lines);
3201 if (body_type_text == NULL) {
3202 res = MAILIMAP_ERROR_MEMORY;
3203 goto free_body_fields;
3204 }
3205
3206 * result = body_type_text;
3207 * index = cur_token;
3208
3209 return MAILIMAP_NO_ERROR;
3210
3211 free_body_fields:
3212 mailimap_body_fields_free(body_fields);
3213 free_media_text:
3214 mailimap_media_text_free(media_text);
3215 err:
3216 return res;
3217}
3218
3219
3220/*
3221 capability = ("AUTH=" auth-type) / atom
3222 ; New capabilities MUST begin with "X" or be
3223 ; registered with IANA as standard or
3224 ; standards-track
3225*/
3226
3227static int
3228mailimap_capability_parse(mailstream * fd, MMAPString * buffer,
3229 size_t * index,
3230 struct mailimap_capability ** result,
3231 size_t progr_rate,
3232 progress_function * progr_fun)
3233{
3234 size_t cur_token;
3235 int type;
3236 char * auth_type;
3237 char * atom;
3238 struct mailimap_capability * cap;
3239 int r;
3240 int res;
3241
3242 cur_token = * index;
3243
3244 auth_type = NULL;
3245 atom = NULL;
3246
3247 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH=");
3248 switch (r) {
3249 case MAILIMAP_NO_ERROR:
3250 type = MAILIMAP_CAPABILITY_AUTH_TYPE;
3251
3252 r = mailimap_auth_type_parse(fd, buffer, &cur_token, &auth_type,
3253 progr_rate, progr_fun);
3254 if (r != MAILIMAP_NO_ERROR) {
3255 res = r;
3256 goto err;
3257 }
3258 break;
3259
3260 case MAILIMAP_ERROR_PARSE:
3261 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
3262 progr_rate, progr_fun);
3263 if (r != MAILIMAP_NO_ERROR) {
3264 res = r;
3265 goto err;
3266 }
3267
3268 type = MAILIMAP_CAPABILITY_NAME;
3269 break;
3270
3271 default:
3272 res = r;
3273 goto err;
3274 }
3275
3276 cap = mailimap_capability_new(type, auth_type, atom);
3277 if (cap == NULL) {
3278 res = MAILIMAP_ERROR_MEMORY;
3279 goto free;
3280 }
3281
3282 * result = cap;
3283 * index = cur_token;
3284
3285 return MAILIMAP_NO_ERROR;
3286
3287 free:
3288 if (auth_type)
3289 mailimap_auth_type_free(auth_type);
3290 if (atom)
3291 mailimap_atom_free(atom);
3292 err:
3293 return res;
3294}
3295
3296/*
3297 capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
3298 *(SP capability)
3299 ; IMAP4rev1 servers which offer RFC 1730
3300 ; compatibility MUST list "IMAP4" as the first
3301 ; capability.
3302*/
3303
3304/*
3305 SP capability *(SP capability)
3306*/
3307
3308static int mailimap_capability_list_parse(mailstream * fd,
3309 MMAPString * buffer,
3310 size_t * index,
3311 clist ** result,
3312 size_t progr_rate,
3313 progress_function * progr_fun)
3314{
3315 size_t cur_token;
3316 clist * list;
3317 int r;
3318
3319 cur_token = * index;
3320
3321 r = mailimap_space_parse(fd, buffer, &cur_token);
3322 if (r != MAILIMAP_NO_ERROR)
3323 return r;
3324
3325 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
3326 (mailimap_struct_parser *)
3327 mailimap_capability_parse,
3328 (mailimap_struct_destructor *)
3329 mailimap_capability_free,
3330 progr_rate, progr_fun);
3331 if (r != MAILIMAP_NO_ERROR)
3332 return r;
3333
3334 * index = cur_token;
3335 * result = list;
3336
3337 return MAILIMAP_NO_ERROR;
3338}
3339
3340static int
3341mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer,
3342 size_t * index,
3343 struct mailimap_capability_data ** result,
3344 size_t progr_rate,
3345 progress_function * progr_fun)
3346{
3347 size_t cur_token;
3348 clist * cap_list;
3349#if 0
3350 clist * cap_list_2;
3351#endif
3352 struct mailimap_capability_data * cap_data;
3353 int r;
3354 int res;
3355
3356 cur_token = * index;
3357
3358 cap_list = NULL;
3359#if 0
3360 cap_list_2 = NULL;
3361#endif
3362
3363 r = mailimap_token_case_insensitive_parse(fd, buffer,
3364 &cur_token, "CAPABILITY");
3365 if (r != MAILIMAP_NO_ERROR) {
3366 res = r;
3367 goto err;
3368 }
3369
3370 r = mailimap_capability_list_parse(fd, buffer, &cur_token,
3371 &cap_list,
3372 progr_rate, progr_fun);
3373
3374 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
3375 res = r;
3376 goto err;
3377 }
3378
3379#if 0
3380 if (!mailimap_space_parse(fd, buffer, &cur_token)) {
3381 res = r;
3382 goto free_list;
3383 }
3384
3385 if (!mailimap_token_case_insensitive_parse(fd, buffer,
3386 &cur_token, "IMAP4rev1"))
3387 goto free_list;
3388
3389 r = mailimap_capability_list_parse(fd, buffer, &cur_token,
3390 &cap_list_2,
3391 progr_rate, progr_fun);
3392
3393 cap_list = g_list_concat(cap_list, cap_list_2);
3394#endif
3395
3396 cap_data = mailimap_capability_data_new(cap_list);
3397 if (cap_data == NULL) {
3398 res = MAILIMAP_ERROR_MEMORY;
3399 goto free_list;
3400 }
3401
3402 * result = cap_data;
3403 * index = cur_token;
3404
3405 return MAILIMAP_NO_ERROR;
3406
3407 free_list:
3408 if (cap_list) {
3409 clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL);
3410 clist_free(cap_list);
3411 }
3412 err:
3413 return res;
3414}
3415
3416/*
3417 UNIMPLEMENTED BECAUSE UNUSED (only in literal)
3418 CHAR8 = %x01-ff
3419 ; any OCTET except NUL, %x00
3420*/
3421
3422/*
3423static gboolean is_char8(gchar ch)
3424{
3425 return (ch != 0x00);
3426}
3427*/
3428
3429
3430/*
3431UNIMPLEMENTED
3432 command = tag SP (command-any / command-auth / command-nonauth /
3433 command-select) CRLF
3434 ; Modal based on state
3435*/
3436
3437/*
3438UNIMPLEMENTED
3439 command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
3440 ; Valid in all states
3441*/
3442
3443/*
3444UNIMPLEMENTED
3445 command-auth = append / create / delete / examine / list / lsub /
3446 rename / select / status / subscribe / unsubscribe
3447 ; Valid only in Authenticated or Selected state
3448*/
3449
3450/*
3451UNIMPLEMENTED
3452 command-nonauth = login / authenticate
3453 ; Valid only when in Not Authenticated state
3454*/
3455
3456/*
3457UNIMPLEMENTED
3458 command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
3459 uid / search
3460 ; Valid only when in Selected state
3461*/
3462
3463/*
3464 continue-req = "+" SP (resp-text / base64) CRLF
3465*/
3466
3467int
3468mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer,
3469 size_t * index,
3470 struct mailimap_continue_req ** result,
3471 size_t progr_rate,
3472 progress_function * progr_fun)
3473{
3474 struct mailimap_resp_text * resp_text;
3475 size_t cur_token;
3476 struct mailimap_continue_req * cont_req;
3477 char * base64;
3478 int type;
3479 int r;
3480 int res;
3481
3482 cur_token = * index;
3483
3484 r = mailimap_plus_parse(fd, buffer, &cur_token);
3485 if (r != MAILIMAP_NO_ERROR)
3486 return r;
3487
3488 r = mailimap_space_parse(fd, buffer, &cur_token);
3489 if (r != MAILIMAP_NO_ERROR)
3490 return r;
3491
3492 resp_text = NULL;
3493 base64 = NULL;
3494
3495 type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */
3496
3497 r = mailimap_base64_parse(fd, buffer, &cur_token, &base64,
3498 progr_rate, progr_fun);
3499
3500 if (r == MAILIMAP_NO_ERROR)
3501 type = MAILIMAP_CONTINUE_REQ_BASE64;
3502
3503 if (r == MAILIMAP_ERROR_PARSE) {
3504 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &resp_text,
3505 progr_rate, progr_fun);
3506
3507 if (r == MAILIMAP_NO_ERROR)
3508 type = MAILIMAP_CONTINUE_REQ_TEXT;
3509 }
3510
3511 if (r != MAILIMAP_NO_ERROR) {
3512 res = r;
3513 goto err;
3514 }
3515
3516 r = mailimap_crlf_parse(fd, buffer, &cur_token);
3517 if (r != MAILIMAP_NO_ERROR) {
3518 res = r;
3519 goto free;
3520 }
3521
3522 cont_req = mailimap_continue_req_new(type, resp_text, base64);
3523 if (cont_req == NULL) {
3524 res = MAILIMAP_ERROR_MEMORY;
3525 goto free;
3526 }
3527
3528 * result = cont_req;
3529 * index = cur_token;
3530
3531 return MAILIMAP_NO_ERROR;
3532
3533 free:
3534 if (base64 != NULL)
3535 mailimap_base64_free(base64);
3536 if (resp_text != NULL)
3537 mailimap_resp_text_free(resp_text);
3538 err:
3539 return res;
3540}
3541
3542/*
3543 UNIMPLEMENTED
3544 copy = "COPY" SP set SP mailbox
3545*/
3546
3547/*
3548 UNIMPLEMENTED
3549 create = "CREATE" SP mailbox
3550 ; Use of INBOX gives a NO error
3551*/
3552
3553/*
3554 UNIMPLEMENTED
3555 date = date-text / DQUOTE date-text DQUOTE
3556*/
3557
3558/*
3559 UNIMPLEMENTED
3560 date-day = 1*2DIGIT
3561 ; Day of month
3562*/
3563
3564/*
3565static gboolean mailimap_date_day_parse(mailstream * fd,
3566 MMAPString * buffer,
3567 guint32 * index,
3568 gint * result)
3569{
3570 guint32 cur_token;
3571 gint digit;
3572 gint number;
3573
3574 cur_token = * index;
3575
3576 if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit))
3577 return FALSE;
3578
3579 number = digit;
3580
3581 if (mailimap_digit_parse(fd, buffer, &cur_token, &digit))
3582 number = number * 10 + digit;
3583
3584 * result = number;
3585 * index = cur_token;
3586
3587 return TRUE;
3588}
3589*/
3590
3591/*
3592 date-day-fixed = (SP DIGIT) / 2DIGIT
3593 ; Fixed-format version of date-day
3594*/
3595
3596static int mailimap_date_day_fixed_parse(mailstream * fd,
3597 MMAPString * buffer,
3598 size_t * index,
3599 int * result)
3600{
3601#ifdef UNSTRICT_SYNTAX
3602 size_t cur_token;
3603 uint32_t day;
3604 int r;
3605
3606 cur_token = * index;
3607
3608 r = mailimap_number_parse(fd, buffer, &cur_token, &day);
3609 if (r != MAILIMAP_NO_ERROR)
3610 return r;
3611
3612 * index = cur_token;
3613 * result = day;
3614
3615 return MAILIMAP_NO_ERROR;
3616
3617#else
3618 size_t cur_token;
3619 int r;
3620
3621 cur_token = * index;
3622
3623 if (mailimap_space_parse(fd, buffer, &cur_token)) {
3624 int digit;
3625
3626 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
3627 if (r != MAILIMAP_NO_ERROR)
3628 return r;
3629
3630 * result = digit;
3631 * index = cur_token;
3632
3633 return MAILIMAP_NO_ERROR;
3634 }
3635 else {
3636 int digit1;
3637 int digit2;
3638
3639 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1);
3640 if (r != MAILIMAP_NO_ERROR)
3641 return r;
3642 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2);
3643 if (r != MAILIMAP_NO_ERROR)
3644 return r;
3645
3646 * result = digit1 * 10 + digit2;
3647 * index = cur_token;
3648
3649 return MAILIMAP_NO_ERROR;
3650 }
3651#endif
3652}
3653
3654
3655/*
3656 date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
3657 "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
3658*/
3659
3660static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer,
3661 size_t * index, int * result)
3662{
3663 size_t cur_token;
3664 int month;
3665
3666 cur_token = * index;
3667
3668 month = mailimap_month_get_token_value(fd, buffer, &cur_token);
3669 if (month == -1)
3670 return MAILIMAP_ERROR_PARSE;
3671
3672 * result = month;
3673 * index = cur_token;
3674
3675 return MAILIMAP_NO_ERROR;
3676}
3677
3678/*
3679 UNIMPLEMENTED
3680 date-text = date-day "-" date-month "-" date-year
3681*/
3682
3683/*
3684static struct mailimap_date_text *
3685mailimap_date_text_new(gint day, gint month, gint year)
3686{
3687 struct mailimap_date_text * date_text;
3688
3689 date_text = g_new(struct mailimap_date_text, 1);
3690 if (date_text == NULL)
3691 return NULL;
3692
3693 date_text->day = day;
3694 date_text->month = month;
3695 date_text->year = year;
3696
3697 return date_text;
3698}
3699
3700static void mailimap_date_text_free(struct mailimap_date_text * date_text)
3701{
3702 g_free(date_text);
3703}
3704
3705static gboolean
3706mailimap_date_text_parse(mailstream * fd, MMAPString * buffer,
3707 guint32 * index, struct mailimap_date_text ** result)
3708{
3709 struct mailimap_date_text * date_text;
3710 gint day;
3711 gint month;
3712 gint year;
3713 guint32 cur_token;
3714
3715 cur_token = * index;
3716
3717 if (!mailimap_date_day_parse(fd, buffer, &cur_token, &day))
3718 return FALSE;
3719
3720 if (!mailimap_minus_parse(fd, buffer, &cur_token))
3721 return FALSE;
3722
3723 if (!mailimap_date_month_parse(fd, buffer, &cur_token, &month))
3724 return FALSE;
3725
3726 if (!mailimap_minus_parse(fd, buffer, &cur_token))
3727 return FALSE;
3728
3729 if (!mailimap_date_year_parse(fd, buffer, &cur_token, &year))
3730 return FALSE;
3731
3732 date_text = mailimap_date_text_new(day, month, year);
3733 if (date_text == NULL)
3734 return FALSE;
3735
3736 * result = date_text;
3737 * index = cur_token;
3738
3739 return TRUE;
3740}
3741*/
3742
3743/*
3744 date-year = 4DIGIT
3745*/
3746
3747static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer,
3748 size_t * index, int * result)
3749{
3750#ifdef UNSTRICT_SYNTAX
3751 uint32_t year;
3752 int r;
3753 size_t cur_token;
3754
3755 cur_token = * index;
3756
3757 r = mailimap_number_parse(fd, buffer, &cur_token, &year);
3758 if (r != MAILIMAP_NO_ERROR)
3759 return r;
3760
3761 * result = year;
3762 * index = cur_token;
3763
3764 return MAILIMAP_NO_ERROR;
3765#else
3766 int i;
3767 size_t cur_token;
3768 int year;
3769 int digit;
3770 int r;
3771
3772 cur_token = * index;
3773 year = 0;
3774
3775 for(i = 0 ; i < 4 ; i ++) {
3776 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
3777 if (r != MAILIMAP_NO_ERROR)
3778 return r;
3779 year = year * 10 + digit;
3780 }
3781
3782 * result = year;
3783 * index = cur_token;
3784
3785 return MAILIMAP_NO_ERROR;
3786#endif
3787}
3788
3789/*
3790 date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
3791 SP time SP zone DQUOTE
3792*/
3793
3794static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer,
3795 size_t * index,
3796 struct mailimap_date_time ** result,
3797 size_t progr_rate,
3798 progress_function * progr_fun)
3799{
3800 int day;
3801 int month;
3802 int year;
3803 int hour;
3804 int min;
3805 int sec;
3806 struct mailimap_date_time * date_time;
3807 size_t cur_token;
3808 int zone;
3809 int r;
3810
3811 cur_token = * index;
3812
3813 r = mailimap_dquote_parse(fd, buffer, &cur_token);
3814 if (r != MAILIMAP_NO_ERROR)
3815 return r;
3816
3817 r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day);
3818 if (r != MAILIMAP_NO_ERROR)
3819 return r;
3820
3821 r = mailimap_minus_parse(fd, buffer, &cur_token);
3822 if (r != MAILIMAP_NO_ERROR)
3823 return r;
3824
3825 r = mailimap_date_month_parse(fd, buffer, &cur_token, &month);
3826 if (r != MAILIMAP_NO_ERROR)
3827 return r;
3828
3829 r = mailimap_minus_parse(fd, buffer, &cur_token);
3830 if (r != MAILIMAP_NO_ERROR)
3831 return r;
3832
3833 r = mailimap_date_year_parse(fd, buffer, &cur_token, &year);
3834 if (r != MAILIMAP_NO_ERROR)
3835 return r;
3836
3837 r = mailimap_space_parse(fd, buffer, &cur_token);
3838 if (r != MAILIMAP_NO_ERROR)
3839 return r;
3840
3841 r = mailimap_time_parse(fd, buffer, &cur_token, &hour, &min, &sec);
3842 if (r != MAILIMAP_NO_ERROR)
3843 return r;
3844
3845 r = mailimap_space_parse(fd, buffer, &cur_token);
3846 if (r != MAILIMAP_NO_ERROR)
3847 return r;
3848
3849 r = mailimap_zone_parse(fd, buffer, &cur_token, &zone);
3850 if (r != MAILIMAP_NO_ERROR)
3851 return r;
3852
3853 r = mailimap_dquote_parse(fd, buffer, &cur_token);
3854 if (r != MAILIMAP_NO_ERROR)
3855 return r;
3856
3857 date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone);
3858 if (date_time == NULL)
3859 return MAILIMAP_ERROR_MEMORY;
3860
3861 * result = date_time;
3862 * index = cur_token;
3863
3864 return MAILIMAP_NO_ERROR;
3865}
3866
3867
3868/*
3869 UNIMPLEMENTED
3870 delete = "DELETE" SP mailbox
3871 ; Use of INBOX gives a NO error
3872*/
3873
3874/*
3875 digit-nz = %x31-39
3876 ; 1-9
3877*/
3878
3879#ifndef UNSTRICT_SYNTAX
3880static int is_digit_nz(char ch)
3881{
3882 return (ch >= '1') && (ch <= '9');
3883}
3884
3885static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer,
3886 size_t * index, int * result)
3887{
3888 size_t cur_token;
3889
3890 cur_token = * index;
3891
3892 if (is_digit_nz(buffer->str[cur_token])) {
3893 * result = buffer->str[cur_token] - '0';
3894 cur_token ++;
3895 * index = cur_token;
3896 return MAILIMAP_NO_ERROR;
3897 }
3898 else
3899 return MAILIMAP_ERROR_PARSE;
3900}
3901#endif
3902
3903/*
3904 envelope = "(" env-date SP env-subject SP env-from SP env-sender SP
3905 env-reply-to SP env-to SP env-cc SP env-bcc SP
3906 env-in-reply-to SP env-message-id ")"
3907*/
3908
3909static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer,
3910 size_t * index,
3911 struct mailimap_envelope ** result,
3912 size_t progr_rate,
3913 progress_function * progr_fun)
3914{
3915 size_t cur_token;
3916 char * date;
3917 char * subject;
3918 struct mailimap_env_from * from;
3919 struct mailimap_env_sender * sender;
3920 struct mailimap_env_reply_to * reply_to;
3921 struct mailimap_env_to * to;
3922 struct mailimap_env_cc * cc;
3923 struct mailimap_env_bcc * bcc;
3924 char * in_reply_to;
3925 char * message_id;
3926 struct mailimap_envelope * envelope;
3927 int r;
3928 int res;
3929
3930 date = NULL;
3931 subject = NULL;
3932 from = NULL;
3933 sender = NULL;
3934 reply_to = NULL;
3935 to = NULL;
3936 cc = NULL;
3937 bcc = NULL;
3938 in_reply_to = NULL;
3939 message_id = NULL;
3940
3941 cur_token = * index;
3942
3943 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
3944 if (r != MAILIMAP_NO_ERROR) {
3945 res = r;
3946 goto err;
3947 }
3948
3949 r = mailimap_env_date_parse(fd, buffer, &cur_token, &date,
3950 progr_rate, progr_fun);
3951 if (r != MAILIMAP_NO_ERROR) {
3952 res = r;
3953 goto err;
3954 }
3955
3956 r = mailimap_space_parse(fd, buffer, &cur_token);
3957 if (r != MAILIMAP_NO_ERROR) {
3958 res = r;
3959 goto date;
3960 }
3961
3962 r = mailimap_env_subject_parse(fd, buffer, &cur_token, &subject,
3963 progr_rate, progr_fun);
3964 if (r != MAILIMAP_NO_ERROR) {
3965 res = r;
3966 goto date;
3967 }
3968
3969 r = mailimap_space_parse(fd, buffer, &cur_token);
3970 if (r != MAILIMAP_NO_ERROR) {
3971 res = r;
3972 goto subject;
3973 }
3974
3975 r = mailimap_env_from_parse(fd, buffer, &cur_token, &from,
3976 progr_rate, progr_fun);
3977 if (r != MAILIMAP_NO_ERROR) {
3978 res = r;
3979 goto subject;
3980 }
3981
3982 r = mailimap_space_parse(fd, buffer, &cur_token);
3983 if (r != MAILIMAP_NO_ERROR) {
3984 res = r;
3985 goto from;
3986 }
3987
3988 r = mailimap_env_sender_parse(fd, buffer, &cur_token, &sender,
3989 progr_rate, progr_fun);
3990 if (r != MAILIMAP_NO_ERROR) {
3991 res = r;
3992 goto from;
3993 }
3994
3995 r = mailimap_space_parse(fd, buffer, &cur_token);
3996 if (r != MAILIMAP_NO_ERROR) {
3997 res = r;
3998 goto sender;
3999 }
4000
4001 r = mailimap_env_reply_to_parse(fd, buffer, &cur_token, &reply_to,
4002 progr_rate, progr_fun);
4003 if (r != MAILIMAP_NO_ERROR) {
4004 res = r;
4005 goto sender;
4006 }
4007
4008 r = mailimap_space_parse(fd, buffer, &cur_token);
4009 if (r != MAILIMAP_NO_ERROR) {
4010 res = r;
4011 goto reply_to;
4012 }
4013
4014 r = mailimap_env_to_parse(fd, buffer, &cur_token, &to,
4015 progr_rate, progr_fun);
4016 if (r != MAILIMAP_NO_ERROR) {
4017 res = r;
4018 goto reply_to;
4019 }
4020
4021 r = mailimap_space_parse(fd, buffer, &cur_token);
4022 if (r != MAILIMAP_NO_ERROR) {
4023 res = r;
4024 goto to;
4025 }
4026
4027 r = mailimap_env_cc_parse(fd, buffer, &cur_token, &cc,
4028 progr_rate, progr_fun);
4029 if (r != MAILIMAP_NO_ERROR) {
4030 res = r;
4031 goto to;
4032 }
4033
4034 r = mailimap_space_parse(fd, buffer, &cur_token);
4035 if (r != MAILIMAP_NO_ERROR) {
4036 res = r;
4037 goto cc;
4038 }
4039
4040 r = mailimap_env_bcc_parse(fd, buffer, &cur_token, &bcc,
4041 progr_rate, progr_fun);
4042 if (r != MAILIMAP_NO_ERROR) {
4043 res = r;
4044 goto cc;
4045 }
4046
4047 r = mailimap_space_parse(fd, buffer, &cur_token);
4048 if (r != MAILIMAP_NO_ERROR) {
4049 res = r;
4050 goto bcc;
4051 }
4052
4053 r = mailimap_env_in_reply_to_parse(fd, buffer, &cur_token, &in_reply_to,
4054 progr_rate, progr_fun);
4055 if (r != MAILIMAP_NO_ERROR) {
4056 res = r;
4057 goto bcc;
4058 }
4059
4060 r = mailimap_space_parse(fd, buffer, &cur_token);
4061 if (r != MAILIMAP_NO_ERROR) {
4062 res = r;
4063 goto in_reply_to;
4064 }
4065
4066 r = mailimap_env_message_id_parse(fd, buffer, &cur_token, &message_id,
4067 progr_rate, progr_fun);
4068 if (r != MAILIMAP_NO_ERROR) {
4069 res = r;
4070 goto in_reply_to;
4071 }
4072
4073 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4074 if (r != MAILIMAP_NO_ERROR) {
4075 res = r;
4076 goto message_id;
4077 }
4078
4079 envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to,
4080 cc, bcc, in_reply_to, message_id);
4081 if (envelope == NULL) {
4082 res = MAILIMAP_ERROR_MEMORY;
4083 goto message_id;
4084 }
4085
4086 * result = envelope;
4087 * index = cur_token;
4088
4089 return MAILIMAP_NO_ERROR;
4090
4091 message_id:
4092 mailimap_env_message_id_free(message_id);
4093 in_reply_to:
4094 mailimap_env_in_reply_to_free(in_reply_to);
4095 bcc:
4096 mailimap_env_bcc_free(bcc);
4097 cc:
4098 mailimap_env_cc_free(cc);
4099 to:
4100 mailimap_env_to_free(to);
4101 reply_to:
4102 mailimap_env_reply_to_free(reply_to);
4103 sender:
4104 mailimap_env_sender_free(sender);
4105 from:
4106 mailimap_env_from_free(from);
4107 subject:
4108 mailimap_env_subject_free(date);
4109 date:
4110 mailimap_env_date_free(date);
4111 err:
4112 return res;
4113}
4114
4115/*
4116 "(" 1*address ")"
4117*/
4118
4119static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer,
4120 size_t * index,
4121 clist ** result,
4122 size_t progr_rate,
4123 progress_function * progr_fun)
4124{
4125 size_t cur_token;
4126 clist * address_list;
4127 int r;
4128 int res;
4129
4130 cur_token = * index;
4131
4132 address_list = NULL;
4133
4134 r = mailimap_nil_parse(fd, buffer, &cur_token);
4135 switch (r) {
4136 case MAILIMAP_NO_ERROR:
4137 address_list = NULL;
4138 break;
4139
4140 case MAILIMAP_ERROR_PARSE:
4141 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4142 if (r != MAILIMAP_NO_ERROR) {
4143 res = r;
4144 goto err;
4145 }
4146
4147 r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &address_list,
4148 (mailimap_struct_parser *)
4149 mailimap_address_parse,
4150 (mailimap_struct_destructor *)
4151 mailimap_address_free,
4152 progr_rate, progr_fun);
4153 if (r != MAILIMAP_NO_ERROR) {
4154 res = r;
4155 goto err;
4156 }
4157
4158 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4159 if (r != MAILIMAP_NO_ERROR) {
4160 res = r;
4161 goto address_list;
4162 }
4163
4164 break;
4165
4166 default:
4167 res = r;
4168 goto err;
4169 }
4170
4171 * result = address_list;
4172 * index = cur_token;
4173
4174 return MAILIMAP_NO_ERROR;
4175
4176 address_list:
4177 if (address_list) {
4178 clist_foreach(address_list, (clist_func) mailimap_address_free, NULL);
4179 clist_free(address_list);
4180 }
4181 err:
4182 return res;
4183}
4184
4185/*
4186 env-bcc = "(" 1*address ")" / nil
4187*/
4188
4189static int
4190mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer,
4191 size_t * index, struct mailimap_env_bcc ** result,
4192 size_t progr_rate,
4193 progress_function * progr_fun)
4194{
4195 clist * list;
4196 size_t cur_token;
4197 struct mailimap_env_bcc * env_bcc;
4198 int r;
4199 int res;
4200
4201 cur_token = * index;
4202 list = NULL;
4203
4204 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4205 progr_rate, progr_fun);
4206 if (r != MAILIMAP_NO_ERROR) {
4207 res = r;
4208 goto err;
4209 }
4210
4211 env_bcc = mailimap_env_bcc_new(list);
4212 if (env_bcc == NULL) {
4213 res = MAILIMAP_ERROR_MEMORY;
4214 goto free;
4215 }
4216
4217 * index = cur_token;
4218 * result = env_bcc;
4219
4220 return MAILIMAP_NO_ERROR;
4221
4222 free:
4223 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4224 clist_free(list);
4225 err:
4226 return res;
4227}
4228
4229/*
4230 env-cc = "(" 1*address ")" / nil
4231*/
4232
4233static int
4234mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer,
4235 size_t * index, struct mailimap_env_cc ** result,
4236 size_t progr_rate,
4237 progress_function * progr_fun)
4238{
4239 clist * list;
4240 size_t cur_token;
4241 struct mailimap_env_cc * env_cc;
4242 int r;
4243 int res;
4244
4245 cur_token = * index;
4246 list = NULL;
4247
4248 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4249 progr_rate, progr_fun);
4250 if (r != MAILIMAP_NO_ERROR) {
4251 res = r;
4252 goto err;
4253 }
4254
4255 env_cc = mailimap_env_cc_new(list);
4256 if (env_cc == NULL) {
4257 res = MAILIMAP_ERROR_MEMORY;
4258 goto free;
4259 }
4260
4261 * index = cur_token;
4262 * result = env_cc;
4263
4264 return MAILIMAP_NO_ERROR;
4265
4266 free:
4267 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4268 clist_free(list);
4269 err:
4270 return res;
4271}
4272
4273/*
4274 env-date = nstring
4275*/
4276
4277static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer,
4278 size_t * index, char ** result,
4279 size_t progr_rate,
4280 progress_function * progr_fun)
4281{
4282 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4283 progr_rate, progr_fun);
4284}
4285
4286/*
4287 env-from = "(" 1*address ")" / nil
4288*/
4289
4290static int
4291mailimap_env_from_parse(mailstream * fd, MMAPString * buffer,
4292 size_t * index, struct mailimap_env_from ** result,
4293 size_t progr_rate,
4294 progress_function * progr_fun)
4295{
4296 clist * list;
4297 size_t cur_token;
4298 struct mailimap_env_from * env_from;
4299 int r;
4300 int res;
4301
4302 cur_token = * index;
4303 list = NULL;
4304
4305 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4306 progr_rate, progr_fun);
4307 if (r != MAILIMAP_NO_ERROR) {
4308 res = r;
4309 goto err;
4310 }
4311
4312 env_from = mailimap_env_from_new(list);
4313 if (env_from == NULL) {
4314 res = MAILIMAP_ERROR_MEMORY;
4315 goto free;
4316 }
4317
4318 * index = cur_token;
4319 * result = env_from;
4320
4321 return MAILIMAP_NO_ERROR;
4322
4323 free:
4324 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4325 clist_free(list);
4326 err:
4327 return res;
4328}
4329
4330/*
4331 env-in-reply-to = nstring
4332*/
4333
4334static int mailimap_env_in_reply_to_parse(mailstream * fd,
4335 MMAPString * buffer,
4336 size_t * index, char ** result,
4337 size_t progr_rate,
4338 progress_function * progr_fun)
4339{
4340 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4341 progr_rate, progr_fun);
4342}
4343
4344/*
4345 env-message-id = nstring
4346*/
4347
4348static int mailimap_env_message_id_parse(mailstream * fd,
4349 MMAPString * buffer,
4350 size_t * index, char ** result,
4351 size_t progr_rate,
4352 progress_function * progr_fun)
4353{
4354 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4355 progr_rate, progr_fun);
4356}
4357
4358/*
4359 env-reply-to = "(" 1*address ")" / nil
4360*/
4361
4362static int
4363mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer,
4364 size_t * index,
4365 struct mailimap_env_reply_to ** result,
4366 size_t progr_rate,
4367 progress_function * progr_fun)
4368{
4369 clist * list;
4370 size_t cur_token;
4371 struct mailimap_env_reply_to * env_reply_to;
4372 int r;
4373 int res;
4374
4375 cur_token = * index;
4376 list = NULL;
4377
4378 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4379 progr_rate, progr_fun);
4380 if (r != MAILIMAP_NO_ERROR) {
4381 res = r;
4382 goto err;
4383 }
4384
4385 env_reply_to = mailimap_env_reply_to_new(list);
4386 if (env_reply_to == NULL) {
4387 res = MAILIMAP_ERROR_MEMORY;
4388 goto free;
4389 }
4390
4391 * index = cur_token;
4392 * result = env_reply_to;
4393
4394 return MAILIMAP_NO_ERROR;
4395
4396 free:
4397 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4398 clist_free(list);
4399 err:
4400 return res;
4401}
4402
4403/*
4404 env-sender = "(" 1*address ")" / nil
4405*/
4406
4407
4408static int
4409mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer,
4410 size_t * index, struct mailimap_env_sender ** result,
4411 size_t progr_rate,
4412 progress_function * progr_fun)
4413{
4414 clist * list;
4415 size_t cur_token;
4416 struct mailimap_env_sender * env_sender;
4417 int r;
4418 int res;
4419
4420 cur_token = * index;
4421 list = NULL;
4422
4423 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4424 progr_rate, progr_fun);
4425 if (r != MAILIMAP_NO_ERROR) {
4426 res = r;
4427 goto err;
4428 }
4429
4430 env_sender = mailimap_env_sender_new(list);
4431 if (env_sender == NULL) {
4432 res = MAILIMAP_ERROR_MEMORY;
4433 goto free;
4434 }
4435
4436 * index = cur_token;
4437 * result = env_sender;
4438
4439 return MAILIMAP_NO_ERROR;
4440
4441 free:
4442 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4443 clist_free(list);
4444 err:
4445 return res;
4446}
4447
4448
4449/*
4450 env-subject = nstring
4451*/
4452
4453static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer,
4454 size_t * index, char ** result,
4455 size_t progr_rate,
4456 progress_function * progr_fun)
4457{
4458 return mailimap_nstring_parse(fd, buffer, index, result, NULL,
4459 progr_rate, progr_fun);
4460}
4461
4462
4463/*
4464 env-to = "(" 1*address ")" / nil
4465*/
4466
4467static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer,
4468 size_t * index,
4469 struct mailimap_env_to ** result,
4470 size_t progr_rate,
4471 progress_function * progr_fun)
4472{
4473 clist * list;
4474 size_t cur_token;
4475 struct mailimap_env_to * env_to;
4476 int r;
4477 int res;
4478
4479 cur_token = * index;
4480 list = NULL;
4481
4482 r = mailimap_address_list_parse(fd, buffer, &cur_token, &list,
4483 progr_rate, progr_fun);
4484 if (r != MAILIMAP_NO_ERROR) {
4485 res = r;
4486 goto err;
4487 }
4488
4489 env_to = mailimap_env_to_new(list);
4490 if (env_to == NULL) {
4491 res = MAILIMAP_ERROR_MEMORY;
4492 goto free;
4493 }
4494
4495 * index = cur_token;
4496 * result = env_to;
4497
4498 return MAILIMAP_NO_ERROR;
4499
4500 free:
4501 clist_foreach(list, (clist_func) mailimap_address_free, NULL);
4502 clist_free(list);
4503 err:
4504 return res;
4505}
4506
4507
4508/*
4509 UNIMPLEMENTED
4510 examine = "EXAMINE" SP mailbox
4511*/
4512
4513/*
4514 UNIMPLEMENTED
4515 fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att /
4516 "(" fetch-att *(SP fetch-att) ")")
4517*/
4518
4519/*
4520 UNIMPLEMENTED
4521 fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
4522 "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
4523 "BODY" ["STRUCTURE"] / "UID" /
4524 "BODY" [".PEEK"] section ["<" number "." nz-number ">"]
4525*/
4526
4527/*
4528 flag = "\Answered" / "\Flagged" / "\Deleted" /
4529 "\Seen" / "\Draft" / flag-keyword / flag-extension
4530 ; Does not include "\Recent"
4531*/
4532
4533static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer,
4534 size_t * index,
4535 struct mailimap_flag ** result,
4536 size_t progr_rate,
4537 progress_function * progr_fun)
4538{
4539 struct mailimap_flag * flag;
4540 size_t cur_token;
4541 char * flag_keyword;
4542 char * flag_extension;
4543 int type;
4544 int r;
4545 int res;
4546
4547 cur_token = * index;
4548
4549 flag_keyword = NULL;
4550 flag_extension = NULL;
4551
4552 type = mailimap_flag_get_token_value(fd, buffer, &cur_token);
4553 if (type == -1) {
4554 r = mailimap_flag_keyword_parse(fd, buffer, &cur_token, &flag_keyword,
4555 progr_rate, progr_fun);
4556 if (r == MAILIMAP_NO_ERROR)
4557 type = MAILIMAP_FLAG_KEYWORD;
4558
4559 if (r == MAILIMAP_ERROR_PARSE) {
4560 r = mailimap_flag_extension_parse(fd, buffer, &cur_token,
4561 &flag_extension,
4562 progr_rate, progr_fun);
4563 type = MAILIMAP_FLAG_EXTENSION;
4564 }
4565
4566 if (r != MAILIMAP_NO_ERROR) {
4567 res = r;
4568 goto err;
4569 }
4570 }
4571
4572 flag = mailimap_flag_new(type, flag_keyword, flag_extension);
4573 if (flag == NULL) {
4574 res = MAILIMAP_ERROR_MEMORY;
4575 goto free;
4576 }
4577
4578 * result = flag;
4579 * index = cur_token;
4580
4581 return MAILIMAP_NO_ERROR;
4582
4583 free:
4584 if (flag_keyword != NULL)
4585 mailimap_flag_keyword_free(flag_keyword);
4586 if (flag_extension != NULL)
4587 mailimap_flag_extension_free(flag_extension);
4588 err:
4589 return res;
4590}
4591
4592/*
4593 flag-extension = "\" atom
4594 ; Future expansion. Client implementations
4595 ; MUST accept flag-extension flags. Server
4596 ; implementations MUST NOT generate
4597 ; flag-extension flags except as defined by
4598 ; future standard or standards-track
4599 ; revisions of this specification.
4600*/
4601
4602static int mailimap_flag_extension_parse(mailstream * fd,
4603 MMAPString * buffer,
4604 size_t * index,
4605 char ** result,
4606 size_t progr_rate,
4607 progress_function * progr_fun)
4608{
4609 size_t cur_token;
4610 char * atom;
4611 int r;
4612
4613 cur_token = * index;
4614
4615 r = mailimap_char_parse(fd, buffer, &cur_token, '\\');
4616 if (r != MAILIMAP_NO_ERROR)
4617 return r;
4618
4619 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
4620 progr_rate, progr_fun);
4621 if (r != MAILIMAP_NO_ERROR)
4622 return r;
4623
4624 * result = atom;
4625 * index = cur_token;
4626
4627 return MAILIMAP_NO_ERROR;
4628}
4629
4630/*
4631 flag-fetch = flag / "\Recent"
4632*/
4633
4634static int
4635mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer,
4636 size_t * index,
4637 struct mailimap_flag_fetch ** result,
4638 size_t progr_rate,
4639 progress_function * progr_fun)
4640{
4641 size_t cur_token;
4642 struct mailimap_flag * flag;
4643 struct mailimap_flag_fetch * flag_fetch;
4644 int type;
4645 int r;
4646 int res;
4647
4648 cur_token = * index;
4649
4650 flag = NULL;
4651
4652 type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */
4653
4654 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
4655 "\\Recent");
4656 if (r == MAILIMAP_NO_ERROR)
4657 type = MAILIMAP_FLAG_FETCH_RECENT;
4658
4659 if (r == MAILIMAP_ERROR_PARSE) {
4660 r = mailimap_flag_parse(fd, buffer, &cur_token, &flag,
4661 progr_rate, progr_fun);
4662 if (r == MAILIMAP_NO_ERROR)
4663 type = MAILIMAP_FLAG_FETCH_OTHER;
4664 }
4665
4666 if (r != MAILIMAP_NO_ERROR) {
4667 res = r;
4668 goto err;
4669 }
4670
4671 flag_fetch = mailimap_flag_fetch_new(type, flag);
4672 if (flag_fetch == NULL) {
4673 res = MAILIMAP_ERROR_MEMORY;
4674 goto free;
4675 }
4676
4677 * index = cur_token;
4678 * result = flag_fetch;
4679
4680 return MAILIMAP_NO_ERROR;
4681
4682 free:
4683 if (flag != NULL)
4684 mailimap_flag_free(flag);
4685 err:
4686 return res;
4687}
4688
4689/*
4690 flag-keyword = atom
4691*/
4692
4693static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer,
4694 size_t * index,
4695 char ** result,
4696 size_t progr_rate,
4697 progress_function * progr_fun)
4698{
4699 return mailimap_atom_parse(fd, buffer, index, result,
4700 progr_rate, progr_fun);
4701}
4702
4703/*
4704 flag-list = "(" [flag *(SP flag)] ")"
4705*/
4706
4707static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer,
4708 size_t * index,
4709 struct mailimap_flag_list ** result,
4710 size_t progr_rate,
4711 progress_function * progr_fun)
4712{
4713 size_t cur_token;
4714 clist * list;
4715 struct mailimap_flag_list * flag_list;
4716 int r;
4717 int res;
4718
4719 list = NULL;
4720 cur_token = * index;
4721
4722 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4723 if (r != MAILIMAP_NO_ERROR) {
4724 res = r;
4725 goto err;
4726 }
4727
4728 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
4729 (mailimap_struct_parser *)
4730 mailimap_flag_parse,
4731 (mailimap_struct_destructor *)
4732 mailimap_flag_free,
4733 progr_rate, progr_fun);
4734
4735 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
4736 res = r;
4737 goto err;
4738 }
4739
4740 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4741 if (r != MAILIMAP_NO_ERROR) {
4742 res = r;
4743 goto free;
4744 }
4745
4746 flag_list = mailimap_flag_list_new(list);
4747 if (flag_list == NULL) {
4748 res = MAILIMAP_ERROR_MEMORY;
4749 goto free;
4750 }
4751
4752 * result = flag_list;
4753 * index = cur_token;
4754
4755 return MAILIMAP_NO_ERROR;
4756
4757 free:
4758 if (list != NULL) {
4759 clist_foreach(list, (clist_func) mailimap_flag_free, NULL);
4760 clist_free(list);
4761 }
4762 err:
4763 return res;
4764}
4765
4766/*
4767 flag-perm = flag / "\*"
4768*/
4769
4770static int
4771mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer,
4772 size_t * index,
4773 struct mailimap_flag_perm ** result,
4774 size_t progr_rate,
4775 progress_function * progr_fun)
4776{
4777 size_t cur_token;
4778 struct mailimap_flag_perm * flag_perm;
4779 struct mailimap_flag * flag;
4780 int type;
4781 int r;
4782 int res;
4783
4784 flag = NULL;
4785 cur_token = * index;
4786 type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */
4787
4788 r = mailimap_flag_parse(fd, buffer, &cur_token, &flag,
4789 progr_rate, progr_fun);
4790 if (r == MAILIMAP_NO_ERROR)
4791 type = MAILIMAP_FLAG_PERM_FLAG;
4792
4793 if (r == MAILIMAP_ERROR_PARSE) {
4794 r = mailimap_token_case_insensitive_parse(fd, buffer,
4795 &cur_token, "\\*");
4796 if (r == MAILIMAP_NO_ERROR)
4797 type = MAILIMAP_FLAG_PERM_ALL;
4798 }
4799
4800 if (r != MAILIMAP_NO_ERROR) {
4801 res = r;
4802 goto err;
4803 }
4804
4805 flag_perm = mailimap_flag_perm_new(type, flag);
4806 if (flag_perm == NULL) {
4807 res = MAILIMAP_ERROR_MEMORY;
4808 goto free;
4809 }
4810
4811 * result = flag_perm;
4812 * index = cur_token;
4813
4814 return MAILIMAP_NO_ERROR;
4815
4816 free:
4817 if (flag != NULL)
4818 mailimap_flag_free(flag);
4819 err:
4820 return res;
4821}
4822
4823/*
4824 greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
4825*/
4826
4827int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer,
4828 size_t * index,
4829 struct mailimap_greeting ** result,
4830 size_t progr_rate,
4831 progress_function * progr_fun)
4832{
4833 size_t cur_token;
4834 struct mailimap_resp_cond_auth * resp_cond_auth;
4835 struct mailimap_resp_cond_bye * resp_cond_bye;
4836 struct mailimap_greeting * greeting;
4837 int type;
4838 int r;
4839 int res;
4840
4841 cur_token = * index;
4842 resp_cond_bye = NULL;
4843 resp_cond_auth = NULL;
4844
4845 r = mailimap_star_parse(fd, buffer, &cur_token);
4846 if (r != MAILIMAP_NO_ERROR) {
4847 res = r;
4848 goto err;
4849 }
4850
4851 r = mailimap_space_parse(fd, buffer, &cur_token);
4852 if (r != MAILIMAP_NO_ERROR) {
4853 res = r;
4854 goto err;
4855 }
4856
4857 type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */
4858
4859 r = mailimap_resp_cond_auth_parse(fd, buffer, &cur_token, &resp_cond_auth,
4860 progr_rate, progr_fun);
4861 if (r == MAILIMAP_NO_ERROR)
4862 type = MAILIMAP_GREETING_RESP_COND_AUTH;
4863
4864 if (r == MAILIMAP_ERROR_PARSE) {
4865 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token,
4866 &resp_cond_bye,
4867 progr_rate, progr_fun);
4868 if (r == MAILIMAP_NO_ERROR)
4869 type = MAILIMAP_GREETING_RESP_COND_BYE;
4870 }
4871
4872 if (r != MAILIMAP_NO_ERROR) {
4873 res = r;
4874 goto err;
4875 }
4876
4877 r = mailimap_crlf_parse(fd, buffer, &cur_token);
4878 if (r != MAILIMAP_NO_ERROR) {
4879 res = r;
4880 goto free;
4881 }
4882
4883 greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye);
4884 if (greeting == NULL) {
4885 res = MAILIMAP_ERROR_MEMORY;
4886 goto free;
4887 }
4888
4889 * result = greeting;
4890 * index = cur_token;
4891
4892 return MAILIMAP_NO_ERROR;
4893
4894 free:
4895 if (resp_cond_auth)
4896 mailimap_resp_cond_auth_free(resp_cond_auth);
4897 if (resp_cond_bye)
4898 mailimap_resp_cond_bye_free(resp_cond_bye);
4899 err:
4900 return res;
4901}
4902
4903/*
4904 header-fld-name = astring
4905*/
4906
4907static int
4908mailimap_header_fld_name_parse(mailstream * fd,
4909 MMAPString * buffer,
4910 size_t * index,
4911 char ** result,
4912 size_t progr_rate,
4913 progress_function * progr_fun)
4914{
4915 return mailimap_astring_parse(fd, buffer, index, result,
4916 progr_rate, progr_fun);
4917}
4918
4919/*
4920 header-list = "(" header-fld-name *(SP header-fld-name) ")"
4921*/
4922
4923static int
4924mailimap_header_list_parse(mailstream * fd, MMAPString * buffer,
4925 size_t * index,
4926 struct mailimap_header_list ** result,
4927 size_t progr_rate,
4928 progress_function * progr_fun)
4929{
4930 size_t cur_token;
4931 struct mailimap_header_list * header_list;
4932 clist * list;
4933 int r;
4934 int res;
4935
4936 cur_token = * index;
4937
4938 list = NULL;
4939
4940 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
4941 if (r != MAILIMAP_NO_ERROR) {
4942 res = r;
4943 goto err;
4944 }
4945
4946 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
4947 (mailimap_struct_parser *)
4948 mailimap_header_fld_name_parse,
4949 (mailimap_struct_destructor *)
4950 mailimap_header_fld_name_free,
4951 progr_rate, progr_fun);
4952 if (r != MAILIMAP_NO_ERROR) {
4953 res = r;
4954 goto err;
4955 }
4956
4957 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
4958 if (r != MAILIMAP_NO_ERROR) {
4959 res = r;
4960 goto free;
4961 }
4962
4963 header_list = mailimap_header_list_new(list);
4964 if (header_list == NULL) {
4965 res = MAILIMAP_ERROR_MEMORY;
4966 goto free;
4967 }
4968
4969 * result = header_list;
4970 * index = cur_token;
4971
4972 return MAILIMAP_NO_ERROR;
4973
4974 free:
4975 clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL);
4976 clist_free(list);
4977 err:
4978 return res;
4979}
4980
4981/*
4982UNIMPLEMENTED
4983 list = "LIST" SP mailbox SP list-mailbox
4984
4985UNIMPLEMENTED
4986 list-mailbox = 1*list-char / string
4987
4988UNIMPLEMENTED
4989 list-char = ATOM-CHAR / list-wildcards / resp-specials
4990*/
4991
4992/*
4993 list-wildcards = "%" / "*"
4994*/
4995
4996static int is_list_wildcards(char ch)
4997{
4998 switch (ch) {
4999 case '%':
5000 case '*':
5001 return TRUE;
5002 }
5003 return FALSE;
5004}
5005
5006
5007/*
5008 literal = "{" number "}" CRLF *CHAR8
5009 ; Number represents the number of CHAR8s
5010*/
5011
5012static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer,
5013 size_t * index, char ** result,
5014 size_t * result_len,
5015 size_t progr_rate,
5016 progress_function * progr_fun)
5017{
5018 size_t cur_token;
5019 uint32_t number;
5020 MMAPString * literal;
5021 char * literal_p;
5022 uint32_t left;
5023 int r;
5024 int res;
5025 size_t number_token;
5026
5027 cur_token = * index;
5028
5029 r = mailimap_oaccolade_parse(fd, buffer, &cur_token);
5030 if (r != MAILIMAP_NO_ERROR) {
5031 res = r;
5032 goto err;
5033 }
5034
5035 number_token = cur_token;
5036
5037 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5038 if (r != MAILIMAP_NO_ERROR) {
5039 res = r;
5040 goto err;
5041 }
5042
5043 r = mailimap_caccolade_parse(fd, buffer, &cur_token);
5044 if (r != MAILIMAP_NO_ERROR) {
5045 res = r;
5046 goto err;
5047 }
5048
5049 r = mailimap_crlf_parse(fd, buffer, &cur_token);
5050 if (r != MAILIMAP_NO_ERROR) {
5051 res = r;
5052 goto err;
5053 }
5054
5055 literal = mmap_string_sized_new(number);
5056 /*
5057 literal = g_new(char, number + 1);
5058 */
5059 if (literal == NULL) {
5060 res = MAILIMAP_ERROR_MEMORY;
5061 goto err;
5062 }
5063
5064 left = buffer->len - cur_token;
5065
5066 if (left >= number) {
5067 /*
5068 if (number > 0)
5069 strncpy(literal, buffer->str + cur_token, number);
5070 literal[number] = 0;
5071 */
5072 if (number > 0)
5073 if (mmap_string_append_len(literal, buffer->str + cur_token,
5074 number) == NULL) {
5075 res = MAILIMAP_ERROR_MEMORY;
5076 goto free_literal;
5077 }
5078 if ((progr_fun != NULL) && (progr_rate != 0))
5079 progr_fun(number, number);
5080
5081 cur_token = cur_token + number;
5082 }
5083 else {
5084 uint32_t needed;
5085 uint32_t current_prog = 0;
5086 uint32_t last_prog = 0;
5087
5088 needed = number - left;
5089 memcpy(literal->str, buffer->str + cur_token, left);
5090 literal->len += left;
5091 literal_p = literal->str + left;
5092 current_prog = left;
5093
5094 while (needed > 0) {
5095 ssize_t read_bytes;
5096
5097 read_bytes = mailstream_read(fd, literal_p, needed);
5098 if (read_bytes == -1) {
5099 res = MAILIMAP_ERROR_STREAM;
5100 goto free_literal;
5101 }
5102 literal->len += read_bytes;
5103 needed -= read_bytes;
5104 literal_p += read_bytes;
5105
5106 current_prog += read_bytes;
5107 if ((progr_fun != NULL) && (progr_rate != 0))
5108 if (current_prog - last_prog > progr_rate) {
5109 progr_fun(current_prog, number);
5110 last_prog = current_prog;
5111 }
5112 }
5113
5114 literal->str[number] = 0;
5115
5116#if 0
5117 literal->str[number] = 0;
5118 if (mmap_string_append_len(buffer, literal->str + left,
5119 literal->len - left) == NULL) {
5120 res = MAILIMAP_ERROR_STREAM;
5121 goto free_literal;
5122 }
5123#endif
5124
5125 if (mmap_string_truncate(buffer, number_token) == NULL) {
5126 res = MAILIMAP_ERROR_MEMORY;
5127 goto free_literal;
5128 }
5129
5130 if (mmap_string_append(buffer, "0}\r\n") == NULL) {
5131 res = MAILIMAP_ERROR_MEMORY;
5132 goto free_literal;
5133 }
5134
5135 cur_token = number_token + 4;
5136 }
5137 if ((progr_fun != NULL) && (progr_rate != 0))
5138 progr_fun(number, number);
5139
5140 if (mailstream_read_line_append(fd, buffer) == NULL) {
5141 res = MAILIMAP_ERROR_STREAM;
5142 goto free_literal;
5143 }
5144
5145 if (mmap_string_ref(literal) < 0) {
5146 res = MAILIMAP_ERROR_MEMORY;
5147 goto free_literal;
5148 }
5149
5150 * result = literal->str;
5151 if (result_len != NULL)
5152 * result_len = literal->len;
5153 * index = cur_token;
5154
5155 return MAILIMAP_NO_ERROR;
5156
5157 free_literal:
5158 mmap_string_free(literal);
5159 err:
5160 return res;
5161}
5162
5163/*
5164 UNIMPLEMENTED
5165 login = "LOGIN" SP userid SP password
5166
5167 UNIMPLEMENTED
5168 lsub = "LSUB" SP mailbox SP list-mailbox
5169*/
5170
5171/*
5172 mailbox = "INBOX" / astring
5173 ; INBOX is case-insensitive. All case variants of
5174 ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
5175 ; not as an astring. An astring which consists of
5176 ; the case-insensitive sequence "I" "N" "B" "O" "X"
5177 ; is considered to be INBOX and not an astring.
5178 ; Refer to section 5.1 for further
5179 ; semantic details of mailbox names.
5180*/
5181
5182static int
5183mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer,
5184 size_t * index, char ** result,
5185 size_t progr_rate,
5186 progress_function * progr_fun)
5187{
5188 size_t cur_token;
5189 char * name;
5190 int r;
5191
5192 cur_token = * index;
5193
5194 r = mailimap_astring_parse(fd, buffer, &cur_token, &name,
5195 progr_rate, progr_fun);
5196 if (r != MAILIMAP_NO_ERROR)
5197 return r;
5198
5199 * result = name;
5200 * index = cur_token;
5201
5202 return MAILIMAP_NO_ERROR;
5203}
5204
5205
5206/*
5207 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
5208 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
5209 "STATUS" SP mailbox SP "("
5210 [status-att SP number *(SP status-att SP number)] ")" /
5211 number SP "EXISTS" / number SP "RECENT"
5212*/
5213
5214/*
5215 "FLAGS" SP flag-list
5216*/
5217
5218static int
5219mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer,
5220 size_t * index,
5221 struct mailimap_flag_list ** result,
5222 size_t progr_rate,
5223 progress_function * progr_fun)
5224{
5225 size_t cur_token;
5226 struct mailimap_flag_list * flag_list;
5227 int r;
5228
5229 cur_token = * index;
5230
5231 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS");
5232 if (r != MAILIMAP_NO_ERROR)
5233 return r;
5234
5235 r = mailimap_space_parse(fd, buffer, &cur_token);
5236 if (r != MAILIMAP_NO_ERROR)
5237 return r;
5238
5239 r = mailimap_flag_list_parse(fd, buffer, &cur_token, &flag_list,
5240 progr_rate, progr_fun);
5241 if (r != MAILIMAP_NO_ERROR)
5242 return r;
5243
5244 * result = flag_list;
5245 * index = cur_token;
5246
5247 return MAILIMAP_NO_ERROR;
5248}
5249
5250
5251/*
5252 "LIST" SP mailbox-list
5253*/
5254
5255static int
5256mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer,
5257 size_t * index,
5258 struct mailimap_mailbox_list ** result,
5259 size_t progr_rate,
5260 progress_function * progr_fun)
5261{
5262 size_t cur_token;
5263 struct mailimap_mailbox_list * mb_list;
5264 int r;
5265 int res;
5266
5267 cur_token = * index;
5268
5269 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST");
5270 if (r != MAILIMAP_NO_ERROR) {
5271 res = r;
5272 return r;
5273 }
5274
5275 r = mailimap_space_parse(fd, buffer, &cur_token);
5276 if (r != MAILIMAP_NO_ERROR) {
5277 res = r;
5278 return r;
5279 }
5280
5281 r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list,
5282 progr_rate, progr_fun);
5283 if (r != MAILIMAP_NO_ERROR) {
5284 res = r;
5285 return r;
5286 }
5287
5288 * result = mb_list;
5289 * index = cur_token;
5290
5291 return MAILIMAP_NO_ERROR;
5292}
5293
5294/*
5295 "LSUB" SP mailbox-list
5296*/
5297
5298static int
5299mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer,
5300 size_t * index,
5301 struct mailimap_mailbox_list ** result,
5302 size_t progr_rate,
5303 progress_function * progr_fun)
5304{
5305 size_t cur_token;
5306 struct mailimap_mailbox_list * mb_list;
5307 int r;
5308
5309 cur_token = * index;
5310
5311 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB");
5312 if (r != MAILIMAP_NO_ERROR)
5313 return r;
5314
5315 r = mailimap_space_parse(fd, buffer, &cur_token);
5316 if (r != MAILIMAP_NO_ERROR)
5317 return r;
5318
5319 r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list,
5320 progr_rate, progr_fun);
5321 if (r != MAILIMAP_NO_ERROR)
5322 return r;
5323
5324 * result = mb_list;
5325 * index = cur_token;
5326
5327 return MAILIMAP_NO_ERROR;
5328}
5329
5330/*
5331 "SEARCH" *(SP nz-number)
5332*/
5333
5334
5335static int
5336mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer,
5337 size_t * index,
5338 clist ** result,
5339 size_t progr_rate,
5340 progress_function * progr_fun)
5341{
5342 size_t cur_token;
5343 size_t final_token;
5344 clist * number_list;
5345 int r;
5346
5347 cur_token = * index;
5348
5349 r = mailimap_token_case_insensitive_parse(fd, buffer,
5350 &cur_token, "SEARCH");
5351 if (r != MAILIMAP_NO_ERROR)
5352 return r;
5353
5354 final_token = cur_token;
5355 number_list = NULL;
5356
5357 r = mailimap_space_parse(fd, buffer, &cur_token);
5358 if (r == MAILIMAP_NO_ERROR) {
5359 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &number_list,
5360 (mailimap_struct_parser *)
5361 mailimap_nz_number_alloc_parse,
5362 (mailimap_struct_destructor *)
5363 mailimap_number_alloc_free,
5364 progr_rate, progr_fun);
5365 if (r == MAILIMAP_NO_ERROR)
5366 final_token = cur_token;
5367 }
5368
5369 * result = number_list;
5370 * index = final_token;
5371
5372 return MAILIMAP_NO_ERROR;
5373}
5374
5375/*
5376 "STATUS" SP mailbox SP "("
5377 [status-att SP number *(SP status-att SP number)] ")"
5378*/
5379
5380/*
5381 status-att SP number
5382*/
5383
5384static int
5385mailimap_status_info_parse(mailstream * fd, MMAPString * buffer,
5386 size_t * index,
5387 struct mailimap_status_info **
5388 result,
5389 size_t progr_rate,
5390 progress_function * progr_fun)
5391{
5392 size_t cur_token;
5393 int status_att;
5394 uint32_t value;
5395 struct mailimap_status_info * info;
5396 int r;
5397
5398 cur_token = * index;
5399 value = 0;
5400
5401 r = mailimap_status_att_parse(fd, buffer, &cur_token, &status_att);
5402 if (r != MAILIMAP_NO_ERROR)
5403 return r;
5404
5405 r = mailimap_space_parse(fd, buffer, &cur_token);
5406 if (r != MAILIMAP_NO_ERROR)
5407 return r;
5408
5409 r = mailimap_number_parse(fd, buffer, &cur_token, &value);
5410 if (r != MAILIMAP_NO_ERROR)
5411 return r;
5412
5413 info = mailimap_status_info_new(status_att, value);
5414 if (info == NULL)
5415 return MAILIMAP_ERROR_MEMORY;
5416
5417 * result = info;
5418 * index = cur_token;
5419
5420 return MAILIMAP_NO_ERROR;
5421}
5422
5423/*
5424 "STATUS" SP mailbox SP "("
5425 [status-att SP number *(SP status-att SP number)] ")"
5426*/
5427
5428static int
5429mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer,
5430 size_t * index, struct
5431 mailimap_mailbox_data_status ** result,
5432 size_t progr_rate,
5433 progress_function * progr_fun)
5434{
5435 size_t cur_token;
5436 char * mb;
5437 clist * status_info_list;
5438 struct mailimap_mailbox_data_status * data_status;
5439 int r;
5440 int res;
5441
5442 cur_token = * index;
5443 mb = NULL;
5444 status_info_list = NULL;
5445
5446 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS");
5447 if (r != MAILIMAP_NO_ERROR) {
5448 res = r;
5449 goto err;
5450 }
5451
5452 r = mailimap_space_parse(fd, buffer, &cur_token);
5453 if (r != MAILIMAP_NO_ERROR) {
5454 res = r;
5455 goto err;
5456 }
5457
5458 r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb,
5459 progr_rate, progr_fun);
5460 if (r != MAILIMAP_NO_ERROR) {
5461 res = r;
5462 goto err;
5463 }
5464
5465 r = mailimap_space_parse(fd, buffer, &cur_token);
5466 if (r != MAILIMAP_NO_ERROR) {
5467 res = r;
5468 goto mailbox;
5469 }
5470
5471 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
5472 if (r != MAILIMAP_NO_ERROR) {
5473 res = r;
5474 goto mailbox;
5475 }
5476
5477 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5478 &status_info_list,
5479 (mailimap_struct_parser *)
5480 mailimap_status_info_parse,
5481 (mailimap_struct_destructor *)
5482 mailimap_status_info_free,
5483 progr_rate, progr_fun);
5484 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5485 res = r;
5486 goto mailbox;
5487 }
5488
5489 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
5490 if (r != MAILIMAP_NO_ERROR) {
5491 res = r;
5492 goto status_info_list;
5493 }
5494
5495 data_status = mailimap_mailbox_data_status_new(mb, status_info_list);
5496 if (data_status == NULL) {
5497 res = MAILIMAP_ERROR_MEMORY;
5498 goto status_info_list;
5499 }
5500
5501 * result = data_status;
5502 * index = cur_token;
5503
5504 return MAILIMAP_NO_ERROR;
5505
5506 status_info_list:
5507 if (status_info_list != NULL) {
5508 clist_foreach(status_info_list, (clist_func) mailimap_status_info_free,
5509 NULL);
5510 clist_free(status_info_list);
5511 }
5512 mailbox:
5513 mailimap_mailbox_free(mb);
5514 err:
5515 return res;
5516}
5517
5518/*
5519 number SP "EXISTS"
5520*/
5521
5522static int
5523mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer,
5524 size_t * index,
5525 uint32_t * result)
5526{
5527 size_t cur_token;
5528 uint32_t number;
5529 int r;
5530
5531 cur_token = * index;
5532
5533 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5534 if (r != MAILIMAP_NO_ERROR)
5535 return r;
5536
5537 r = mailimap_space_parse(fd, buffer, &cur_token);
5538 if (r != MAILIMAP_NO_ERROR)
5539 return r;
5540
5541 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS");
5542 if (r != MAILIMAP_NO_ERROR)
5543 return r;
5544
5545 * result = number;
5546 * index = cur_token;
5547
5548 return MAILIMAP_NO_ERROR;
5549}
5550
5551/*
5552 number SP "RECENT"
5553*/
5554
5555static int
5556mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer,
5557 size_t * index,
5558 uint32_t * result)
5559{
5560 size_t cur_token;
5561 uint32_t number;
5562 int r;
5563
5564 cur_token = * index;
5565
5566 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
5567 if (r != MAILIMAP_NO_ERROR)
5568 return r;
5569
5570 r = mailimap_space_parse(fd, buffer, &cur_token);
5571 if (r != MAILIMAP_NO_ERROR)
5572 return r;
5573
5574 r = mailimap_token_case_insensitive_parse(fd, buffer,
5575 &cur_token, "RECENT");
5576 if (r != MAILIMAP_NO_ERROR)
5577 return r;
5578
5579 * result = number;
5580 * index = cur_token;
5581
5582 return MAILIMAP_NO_ERROR;
5583}
5584
5585/*
5586 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
5587 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
5588 "STATUS" SP mailbox SP "("
5589 [status-att SP number *(SP status-att SP number)] ")" /
5590 number SP "EXISTS" / number SP "RECENT"
5591*/
5592
5593static int
5594mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer,
5595 size_t * index,
5596 struct mailimap_mailbox_data ** result,
5597 size_t progr_rate,
5598 progress_function * progr_fun)
5599{
5600 int type;
5601 struct mailimap_flag_list * data_flags;
5602 struct mailimap_mailbox_list * data_list;
5603 struct mailimap_mailbox_list * data_lsub;
5604 clist * data_search;
5605 struct mailimap_mailbox_data_status * data_status;
5606 uint32_t data_exists;
5607 uint32_t data_recent;
5608
5609 struct mailimap_mailbox_data * mailbox_data;
5610 size_t cur_token;
5611 int r;
5612 int res;
5613
5614 cur_token = * index;
5615
5616 data_flags = NULL;
5617 data_list = NULL;
5618 data_lsub = NULL;
5619 data_search = NULL;
5620 data_status = NULL;
5621 data_exists = 0;
5622 data_recent = 0;
5623
5624 type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */
5625
5626 r = mailimap_mailbox_data_flags_parse(fd, buffer, &cur_token,
5627 &data_flags,
5628 progr_rate, progr_fun);
5629 if (r == MAILIMAP_NO_ERROR)
5630 type = MAILIMAP_MAILBOX_DATA_FLAGS;
5631
5632 if (r == MAILIMAP_ERROR_PARSE) {
5633 r = mailimap_mailbox_data_list_parse(fd, buffer, &cur_token,
5634 &data_list,
5635 progr_rate, progr_fun);
5636 if (r == MAILIMAP_NO_ERROR)
5637 type = MAILIMAP_MAILBOX_DATA_LIST;
5638 }
5639
5640 if (r == MAILIMAP_ERROR_PARSE) {
5641 r = mailimap_mailbox_data_lsub_parse(fd, buffer, &cur_token,
5642 &data_lsub,
5643 progr_rate, progr_fun);
5644 if (r == MAILIMAP_NO_ERROR)
5645 type = MAILIMAP_MAILBOX_DATA_LSUB;
5646 }
5647
5648 if (r == MAILIMAP_ERROR_PARSE) {
5649 r = mailimap_mailbox_data_search_parse(fd, buffer, &cur_token,
5650 &data_search,
5651 progr_rate, progr_fun);
5652 if (r == MAILIMAP_NO_ERROR)
5653 type = MAILIMAP_MAILBOX_DATA_SEARCH;
5654 }
5655
5656 if (r == MAILIMAP_ERROR_PARSE) {
5657 r = mailimap_mailbox_data_status_parse(fd, buffer, &cur_token,
5658 &data_status,
5659 progr_rate, progr_fun);
5660 if (r == MAILIMAP_NO_ERROR)
5661 type = MAILIMAP_MAILBOX_DATA_STATUS;
5662 }
5663
5664 if (r == MAILIMAP_ERROR_PARSE) {
5665 r = mailimap_mailbox_data_exists_parse(fd, buffer, &cur_token,
5666 &data_exists);
5667 if (r == MAILIMAP_NO_ERROR)
5668 type = MAILIMAP_MAILBOX_DATA_EXISTS;
5669 }
5670
5671 if (r == MAILIMAP_ERROR_PARSE) {
5672 r = mailimap_mailbox_data_recent_parse(fd, buffer, &cur_token,
5673 &data_recent);
5674 if (r == MAILIMAP_NO_ERROR)
5675 type = MAILIMAP_MAILBOX_DATA_RECENT;
5676 }
5677
5678 if (r != MAILIMAP_NO_ERROR) {
5679 res = r;
5680 goto err;
5681 }
5682
5683 mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list,
5684 data_lsub, data_search,
5685 data_status,
5686 data_exists, data_recent);
5687
5688 if (mailbox_data == NULL) {
5689 res = MAILIMAP_ERROR_MEMORY;
5690 goto free;
5691 }
5692
5693 * result = mailbox_data;
5694 * index = cur_token;
5695
5696 return MAILIMAP_NO_ERROR;
5697
5698 free:
5699 if (data_flags != NULL)
5700 mailimap_flag_list_free(data_flags);
5701 if (data_list != NULL)
5702 mailimap_mailbox_list_free(data_list);
5703 if (data_lsub != NULL)
5704 mailimap_mailbox_list_free(data_lsub);
5705 if (data_search != NULL)
5706 mailimap_mailbox_data_search_free(data_search);
5707 if (data_status != NULL)
5708 mailimap_mailbox_data_status_free(data_status);
5709 err:
5710 return res;
5711}
5712
5713/*
5714 mailbox-list = "(" [mbx-list-flags] ")" SP
5715 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
5716*/
5717
5718/*
5719 DQUOTE QUOTED-CHAR DQUOTE
5720*/
5721
5722static int
5723mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer,
5724 size_t * index,
5725 char * result)
5726{
5727 size_t cur_token;
5728 char ch;
5729 int r;
5730
5731 cur_token = * index;
5732
5733 r = mailimap_dquote_parse(fd, buffer, &cur_token);
5734 if (r != MAILIMAP_NO_ERROR)
5735 return r;
5736
5737 r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch);
5738 if (r != MAILIMAP_NO_ERROR)
5739 return r;
5740
5741 r = mailimap_dquote_parse(fd, buffer, &cur_token);
5742 if (r != MAILIMAP_NO_ERROR)
5743 return r;
5744
5745 * index = cur_token;
5746 * result = ch;
5747
5748 return MAILIMAP_NO_ERROR;
5749}
5750
5751static int
5752mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer,
5753 size_t * index,
5754 struct mailimap_mailbox_list ** result,
5755 size_t progr_rate,
5756 progress_function * progr_fun)
5757{
5758 struct mailimap_mailbox_list * mb_list;
5759 struct mailimap_mbx_list_flags * mb_flag_list;
5760 char ch;
5761 char * mb;
5762 size_t cur_token;
5763 int r;
5764 int res;
5765
5766 cur_token = * index;
5767
5768 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
5769 if (r != MAILIMAP_NO_ERROR) {
5770 res = r;
5771 goto err;
5772 }
5773
5774 mb_flag_list = NULL;
5775 ch = 0;
5776 mb = NULL;
5777
5778 r = mailimap_mbx_list_flags_parse(fd, buffer, &cur_token,
5779 &mb_flag_list, progr_rate, progr_fun);
5780 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5781 res = r;
5782 goto err;
5783 }
5784
5785 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
5786 if (r != MAILIMAP_NO_ERROR) {
5787 res = r;
5788 goto free_list_flags;
5789 }
5790
5791 r = mailimap_space_parse(fd, buffer, &cur_token);
5792 if (r != MAILIMAP_NO_ERROR) {
5793 res = r;
5794 goto free_list_flags;
5795 }
5796
5797 r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, &cur_token, &ch);
5798 if (r == MAILIMAP_ERROR_PARSE)
5799 r = mailimap_nil_parse(fd, buffer, &cur_token);
5800
5801 if (r != MAILIMAP_NO_ERROR) {
5802 res = r;
5803 goto free_list_flags;
5804 }
5805
5806 r = mailimap_space_parse(fd, buffer, &cur_token);
5807 if (r != MAILIMAP_NO_ERROR) {
5808 res = r;
5809 goto free_list_flags;
5810 }
5811
5812 r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb,
5813 progr_rate, progr_fun);
5814 if (r != MAILIMAP_NO_ERROR) {
5815 res = r;
5816 goto free_list_flags;
5817 }
5818
5819 mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb);
5820 if (mb_list == NULL) {
5821 res = MAILIMAP_ERROR_MEMORY;
5822 goto free_mailbox;
5823 }
5824
5825 * result = mb_list;
5826 * index = cur_token;
5827
5828 return MAILIMAP_NO_ERROR;
5829
5830 free_mailbox:
5831 mailimap_mailbox_free(mb);
5832 free_list_flags:
5833 if (mb_flag_list != NULL)
5834 mailimap_mbx_list_flags_free(mb_flag_list);
5835 err:
5836 return res;
5837}
5838
5839/*
5840 mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
5841 *(SP mbx-list-oflag) /
5842 mbx-list-oflag *(SP mbx-list-oflag)
5843*/
5844
5845static int
5846mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer,
5847 size_t * index,
5848 struct mailimap_mbx_list_flags ** result,
5849 size_t progr_rate,
5850 progress_function * progr_fun)
5851{
5852 struct mailimap_mbx_list_flags * mbx_list_flag;
5853 size_t cur_token;
5854 clist * oflags;
5855 clist * oflags_2;
5856 int sflag;
5857 int type;
5858 int r;
5859 int res;
5860 size_t final_token;
5861 int try_sflag;
5862
5863 cur_token = * index;
5864 final_token = cur_token;
5865
5866 oflags = clist_new();
5867 if (oflags == NULL) {
5868 res = MAILIMAP_ERROR_MEMORY;
5869 goto err;
5870 }
5871
5872 sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR;
5873 oflags_2 = NULL;
5874
5875 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5876 &oflags_2,
5877 (mailimap_struct_parser *)
5878 mailimap_mbx_list_oflag_no_sflag_parse,
5879 (mailimap_struct_destructor *)
5880 mailimap_mbx_list_oflag_free,
5881 progr_rate, progr_fun);
5882 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5883 res = r;
5884 goto free;
5885 }
5886
5887 try_sflag = 1;
5888 if (r == MAILIMAP_NO_ERROR) {
5889 clist_concat(oflags, oflags_2);
5890 clist_free(oflags_2);
5891
5892 final_token = cur_token;
5893 try_sflag = 0;
5894 r = mailimap_space_parse(fd, buffer, &cur_token);
5895 if (r == MAILIMAP_NO_ERROR)
5896 try_sflag = 1;
5897 }
5898
5899 type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG;
5900 if (try_sflag) {
5901 r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag);
5902 switch (r) {
5903 case MAILIMAP_ERROR_PARSE:
5904 type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG;
5905 break;
5906
5907 case MAILIMAP_NO_ERROR:
5908 type = MAILIMAP_MBX_LIST_FLAGS_SFLAG;
5909
5910 final_token = cur_token;
5911 r = mailimap_space_parse(fd, buffer, &cur_token);
5912 if (r == MAILIMAP_NO_ERROR) {
5913 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
5914 &oflags_2,
5915 (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse,
5916 (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free,
5917 progr_rate, progr_fun);
5918 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
5919 res = r;
5920 goto err;
5921 }
5922
5923 if (r == MAILIMAP_NO_ERROR) {
5924 clist_concat(oflags, oflags_2);
5925 clist_free(oflags_2);
5926
5927 final_token = cur_token;
5928 }
5929 }
5930
5931 break;
5932
5933 default:
5934 res = r;
5935 goto free;
5936 }
5937 }
5938
5939 if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) {
5940 res = MAILIMAP_ERROR_PARSE;
5941 goto free;
5942 }
5943
5944 cur_token = final_token;
5945 mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag);
5946 if (mbx_list_flag == NULL) {
5947 res = MAILIMAP_ERROR_MEMORY;
5948 goto free;
5949 }
5950
5951 * result = mbx_list_flag;
5952 * index = cur_token;
5953
5954 return MAILIMAP_NO_ERROR;
5955
5956free:
5957 clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL);
5958 clist_free(oflags);
5959err:
5960 return res;
5961}
5962
5963/*
5964 mbx-list-oflag = "\Noinferiors" / flag-extension
5965 ; Other flags; multiple possible per LIST response
5966*/
5967
5968static int
5969mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer,
5970 size_t * index,
5971 struct mailimap_mbx_list_oflag ** result,
5972 size_t progr_rate,
5973 progress_function * progr_fun)
5974{
5975 int type;
5976 size_t cur_token;
5977 struct mailimap_mbx_list_oflag * oflag;
5978 char * flag_ext;
5979 int r;
5980 int res;
5981 int sflag_type;
5982
5983 cur_token = * index;
5984 flag_ext = NULL;
5985 type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */
5986
5987 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
5988 "\\Noinferiors");
5989 if (r == MAILIMAP_NO_ERROR)
5990 type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS;
5991
5992 if (r == MAILIMAP_ERROR_PARSE) {
5993 r = mailimap_flag_extension_parse(fd, buffer, &cur_token,
5994 &flag_ext, progr_rate, progr_fun);
5995 if (r == MAILIMAP_NO_ERROR)
5996 type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT;
5997 }
5998
5999 if (r != MAILIMAP_NO_ERROR) {
6000 res = r;
6001 goto err;
6002 }
6003
6004 oflag = mailimap_mbx_list_oflag_new(type, flag_ext);
6005 if (oflag == NULL) {
6006 res = MAILIMAP_ERROR_MEMORY;
6007 goto free;
6008 }
6009
6010 * result = oflag;
6011 * index = cur_token;
6012
6013 return MAILIMAP_NO_ERROR;
6014
6015 free:
6016 if (flag_ext != NULL)
6017 mailimap_flag_extension_free(flag_ext);
6018 err:
6019 return res;
6020}
6021
6022static int
6023mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer,
6024 size_t * index,
6025 struct mailimap_mbx_list_oflag ** result,
6026 size_t progr_rate,
6027 progress_function * progr_fun)
6028{
6029 size_t cur_token;
6030 int sflag_type;
6031 int r;
6032
6033 cur_token = * index;
6034
6035 r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag_type);
6036 if (r == MAILIMAP_NO_ERROR)
6037 return MAILIMAP_ERROR_PARSE;
6038
6039 return mailimap_mbx_list_oflag_parse(fd, buffer, index, result,
6040 progr_rate, progr_fun);
6041}
6042
6043
6044/*
6045 mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
6046 ; Selectability flags; only one per LIST response
6047*/
6048
6049static int
6050mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer,
6051 size_t * index,
6052 int * result)
6053{
6054 int type;
6055 size_t cur_token;
6056
6057 cur_token = * index;
6058
6059 type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token);
6060 if (type == -1)
6061 return MAILIMAP_ERROR_PARSE;
6062
6063 * result = type;
6064 * index = cur_token;
6065
6066 return MAILIMAP_NO_ERROR;
6067}
6068
6069
6070/*
6071 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6072 "VIDEO") DQUOTE) / string) SP media-subtype
6073 ; Defined in [MIME-IMT]
6074*/
6075
6076/*
6077 DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6078 "VIDEO") DQUOTE
6079*/
6080
6081static int
6082mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer,
6083 size_t * index,
6084 int * result)
6085{
6086 size_t cur_token;
6087 int type;
6088 int r;
6089
6090 cur_token = * index;
6091
6092 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6093 if (r != MAILIMAP_NO_ERROR)
6094 return r;
6095
6096 type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token);
6097 if (type == -1)
6098 return MAILIMAP_ERROR_PARSE;
6099
6100 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6101 if (r != MAILIMAP_NO_ERROR)
6102 return FALSE;
6103
6104 * index = cur_token;
6105 * result = type;
6106
6107 return MAILIMAP_NO_ERROR;
6108}
6109
6110/*
6111 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
6112 "VIDEO") DQUOTE) / string) SP media-subtype
6113 ; Defined in [MIME-IMT]
6114*/
6115
6116static int
6117mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer,
6118 size_t * index,
6119 struct mailimap_media_basic ** result,
6120 size_t progr_rate,
6121 progress_function * progr_fun)
6122{
6123 size_t cur_token;
6124 int type;
6125 char * basic_type;
6126 char * subtype;
6127 struct mailimap_media_basic * media_basic;
6128 int r;
6129 int res;
6130
6131 cur_token = * index;
6132
6133 basic_type = NULL;
6134 subtype = NULL;
6135
6136 r = mailimap_media_basic_standard_parse(fd, buffer, &cur_token,
6137 &type);
6138
6139 if (r == MAILIMAP_ERROR_PARSE) {
6140 r = mailimap_string_parse(fd, buffer, &cur_token, &basic_type, NULL,
6141 progr_rate, progr_fun);
6142 if (r == MAILIMAP_NO_ERROR)
6143 type = MAILIMAP_MEDIA_BASIC_OTHER;
6144 }
6145
6146 if (r != MAILIMAP_NO_ERROR) {
6147 res = r;
6148 goto err;
6149 }
6150
6151 r = mailimap_space_parse(fd, buffer, &cur_token);
6152 if (r != MAILIMAP_NO_ERROR) {
6153 res = r;
6154 goto free_basic_type;
6155 }
6156
6157 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &subtype,
6158 progr_rate, progr_fun);
6159 if (r != MAILIMAP_NO_ERROR) {
6160 res = r;
6161 goto free_basic_type;
6162 }
6163
6164 media_basic = mailimap_media_basic_new(type, basic_type, subtype);
6165 if (media_basic == NULL) {
6166 res = MAILIMAP_ERROR_MEMORY;
6167 goto free_subtype;
6168 }
6169
6170 * result = media_basic;
6171 * index = cur_token;
6172
6173 return MAILIMAP_NO_ERROR;
6174
6175 free_subtype:
6176 mailimap_media_subtype_free(subtype);
6177 free_basic_type:
6178 if (basic_type != NULL)
6179 mailimap_string_free(basic_type);
6180 err:
6181 return res;
6182}
6183
6184
6185/*
6186 media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
6187 ; Defined in [MIME-IMT]
6188*/
6189
6190static int
6191mailimap_media_message_parse(mailstream * fd, MMAPString * buffer,
6192 size_t * index)
6193{
6194 size_t cur_token;
6195 int r;
6196
6197 cur_token = * index;
6198
6199 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6200 if (r != MAILIMAP_NO_ERROR)
6201 return r;
6202
6203 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6204 "MESSAGE");
6205 if (r != MAILIMAP_NO_ERROR)
6206 return r;
6207
6208 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6209 if (r != MAILIMAP_NO_ERROR)
6210 return r;
6211
6212 r = mailimap_space_parse(fd, buffer, &cur_token);
6213 if (r != MAILIMAP_NO_ERROR)
6214 return r;
6215
6216 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6217 if (r != MAILIMAP_NO_ERROR)
6218 return r;
6219
6220 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6221 "RFC822");
6222 if (r != MAILIMAP_NO_ERROR)
6223 return r;
6224
6225 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6226 if (r != MAILIMAP_NO_ERROR)
6227 return r;
6228
6229 * index = cur_token;
6230
6231 return MAILIMAP_NO_ERROR;
6232}
6233
6234/*
6235 media-subtype = string
6236 ; Defined in [MIME-IMT]
6237*/
6238
6239static int
6240mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer,
6241 size_t * index,
6242 char ** result,
6243 size_t progr_rate,
6244 progress_function * progr_fun)
6245{
6246 return mailimap_string_parse(fd, buffer, index, result, NULL,
6247 progr_rate, progr_fun);
6248}
6249
6250/*
6251 media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
6252 ; Defined in [MIME-IMT]
6253*/
6254
6255static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer,
6256 size_t * index,
6257 char ** result,
6258 size_t progr_rate,
6259 progress_function * progr_fun)
6260{
6261 size_t cur_token;
6262 char * media_subtype;
6263 int r;
6264
6265 cur_token = * index;
6266
6267 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6268 if (r != MAILIMAP_NO_ERROR)
6269 return r;
6270
6271 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6272 "TEXT");
6273 if (r != MAILIMAP_NO_ERROR)
6274 return r;
6275
6276 r = mailimap_dquote_parse(fd, buffer, &cur_token);
6277 if (r != MAILIMAP_NO_ERROR)
6278 return r;
6279
6280 r = mailimap_space_parse(fd, buffer, &cur_token);
6281 if (r != MAILIMAP_NO_ERROR)
6282 return r;
6283
6284 r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype,
6285 progr_rate, progr_fun);
6286 if (r != MAILIMAP_NO_ERROR)
6287 return r;
6288
6289 * result = media_subtype;
6290 * index = cur_token;
6291
6292 return MAILIMAP_NO_ERROR;
6293}
6294
6295
6296/*
6297 message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
6298*/
6299
6300
6301static int
6302mailimap_message_data_parse(mailstream * fd, MMAPString * buffer,
6303 size_t * index,
6304 struct mailimap_message_data ** result,
6305 size_t progr_rate,
6306 progress_function * progr_fun)
6307{
6308 size_t cur_token;
6309 uint32_t number;
6310 int type;
6311 struct mailimap_msg_att * msg_att;
6312 struct mailimap_message_data * msg_data;
6313 int r;
6314 int res;
6315
6316 cur_token = * index;
6317 msg_att = NULL;
6318
6319 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
6320 if (r != MAILIMAP_NO_ERROR) {
6321 res = r;
6322 goto err;
6323 }
6324
6325 r = mailimap_space_parse(fd, buffer, &cur_token);
6326 if (r != MAILIMAP_NO_ERROR) {
6327 res = r;
6328 goto err;
6329 }
6330
6331 type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */
6332
6333 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6334 "EXPUNGE");
6335 if (r == MAILIMAP_NO_ERROR)
6336 type = MAILIMAP_MESSAGE_DATA_EXPUNGE;
6337
6338 if (r == MAILIMAP_ERROR_PARSE) {
6339 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6340 "FETCH");
6341 if (r != MAILIMAP_NO_ERROR) {
6342 res = r;
6343 goto err;
6344 }
6345
6346 r = mailimap_space_parse(fd, buffer, &cur_token);
6347 if (r != MAILIMAP_NO_ERROR) {
6348 res = r;
6349 goto err;
6350 }
6351
6352 r = mailimap_msg_att_parse(fd, buffer, &cur_token, &msg_att,
6353 progr_rate, progr_fun);
6354 if (r != MAILIMAP_NO_ERROR) {
6355 res = r;
6356 goto err;
6357 }
6358
6359 type = MAILIMAP_MESSAGE_DATA_FETCH;
6360 }
6361
6362 if (r != MAILIMAP_NO_ERROR) {
6363 res = r;
6364 goto err;
6365 }
6366
6367 msg_data = mailimap_message_data_new(number, type, msg_att);
6368 if (msg_data == NULL) {
6369 res = MAILIMAP_ERROR_MEMORY;
6370 goto free_msg_att;
6371 }
6372
6373 * result = msg_data;
6374 * index = cur_token;
6375
6376 return MAILIMAP_NO_ERROR;
6377
6378 free_msg_att:
6379 if (msg_att != NULL)
6380 mailimap_msg_att_free(msg_att);
6381 err:
6382 return res;
6383}
6384
6385/*
6386 msg-att = "(" (msg-att-dynamic / msg-att-static)
6387 *(SP (msg-att-dynamic / msg-att-static)) ")"
6388*/
6389
6390/*
6391 msg-att-dynamic / msg-att-static
6392*/
6393
6394static int
6395mailimap_msg_att_item_parse(mailstream * fd, MMAPString * buffer,
6396 size_t * index,
6397 struct mailimap_msg_att_item ** result,
6398 size_t progr_rate,
6399 progress_function * progr_fun)
6400{
6401 int type;
6402 struct mailimap_msg_att_dynamic * msg_att_dynamic;
6403 struct mailimap_msg_att_static * msg_att_static;
6404 size_t cur_token;
6405 struct mailimap_msg_att_item * item;
6406 int r;
6407 int res;
6408
6409 cur_token = * index;
6410
6411 msg_att_dynamic = NULL;
6412 msg_att_static = NULL;
6413
6414 type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */
6415
6416 r = mailimap_msg_att_dynamic_parse(fd, buffer, &cur_token,
6417 &msg_att_dynamic,
6418 progr_rate, progr_fun);
6419 if (r == MAILIMAP_NO_ERROR)
6420 type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC;
6421
6422 if (r == MAILIMAP_ERROR_PARSE) {
6423 r = mailimap_msg_att_static_parse(fd, buffer, &cur_token,
6424 &msg_att_static,
6425 progr_rate, progr_fun);
6426 if (r == MAILIMAP_NO_ERROR)
6427 type = MAILIMAP_MSG_ATT_ITEM_STATIC;
6428 }
6429
6430 if (r != MAILIMAP_NO_ERROR) {
6431 res = r;
6432 goto err;
6433 }
6434
6435 item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static);
6436 if (item == NULL) {
6437 res = MAILIMAP_ERROR_MEMORY;
6438 goto free;
6439 }
6440
6441 * result = item;
6442 * index = cur_token;
6443
6444 return MAILIMAP_NO_ERROR;
6445
6446 free:
6447 if (msg_att_dynamic != NULL)
6448 mailimap_msg_att_dynamic_free(msg_att_dynamic);
6449 if (msg_att_static != NULL)
6450 mailimap_msg_att_static_free(msg_att_static);
6451 err:
6452 return res;
6453}
6454
6455/*
6456 msg-att = "(" (msg-att-dynamic / msg-att-static)
6457 *(SP (msg-att-dynamic / msg-att-static)) ")"
6458*/
6459
6460static int
6461mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer,
6462 size_t * index, struct mailimap_msg_att ** result,
6463 size_t progr_rate,
6464 progress_function * progr_fun)
6465{
6466 size_t cur_token;
6467 clist * list;
6468 struct mailimap_msg_att * msg_att;
6469 int r;
6470 int res;
6471
6472 cur_token = * index;
6473 list = NULL;
6474
6475 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
6476 if (r != MAILIMAP_NO_ERROR) {
6477 res = r;
6478 goto err;
6479 }
6480
6481 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list,
6482 (mailimap_struct_parser *)
6483 mailimap_msg_att_item_parse,
6484 (mailimap_struct_destructor *)
6485 mailimap_msg_att_item_free,
6486 progr_rate, progr_fun);
6487 if (r != MAILIMAP_NO_ERROR) {
6488 res = r;
6489 goto err;
6490 }
6491
6492 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
6493 if (r != MAILIMAP_NO_ERROR) {
6494 res = r;
6495 goto free;
6496 }
6497
6498 msg_att = mailimap_msg_att_new(list);
6499 if (msg_att == NULL) {
6500 res = MAILIMAP_ERROR_MEMORY;
6501 goto free;
6502 }
6503
6504 * index = cur_token;
6505 * result = msg_att;
6506
6507 return MAILIMAP_NO_ERROR;
6508
6509 free:
6510 clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL);
6511 clist_free(list);
6512 err:
6513 return res;
6514}
6515
6516/*
6517 msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
6518 ; MAY change for a message
6519*/
6520
6521
6522static int
6523mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer,
6524 size_t * index,
6525 struct mailimap_msg_att_dynamic ** result,
6526 size_t progr_rate,
6527 progress_function * progr_fun)
6528{
6529 clist * list;
6530 struct mailimap_msg_att_dynamic * msg_att_dyn;
6531 size_t cur_token;
6532 int r;
6533 int res;
6534
6535 cur_token = * index;
6536
6537 list = NULL;
6538
6539 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS");
6540 if (r != MAILIMAP_NO_ERROR) {
6541 res = r;
6542 goto err;
6543 }
6544
6545 r = mailimap_space_parse(fd, buffer, &cur_token);
6546 if (r != MAILIMAP_NO_ERROR) {
6547 res = r;
6548 goto err;
6549 }
6550
6551 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
6552 if (r != MAILIMAP_NO_ERROR) {
6553 res = r;
6554 goto err;
6555 }
6556
6557 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token,
6558 &list,
6559 (mailimap_struct_parser *)
6560 mailimap_flag_fetch_parse,
6561 (mailimap_struct_destructor *)
6562 mailimap_flag_fetch_free,
6563 progr_rate, progr_fun);
6564 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
6565 res = r;
6566 goto err;
6567 }
6568
6569 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
6570 if (r != MAILIMAP_NO_ERROR) {
6571 res = r;
6572 goto free;
6573 }
6574
6575 msg_att_dyn = mailimap_msg_att_dynamic_new(list);
6576 if (msg_att_dyn == NULL) {
6577 res = MAILIMAP_ERROR_MEMORY;
6578 goto free;
6579 }
6580
6581 * result = msg_att_dyn;
6582 * index = cur_token;
6583
6584 return MAILIMAP_NO_ERROR;
6585
6586 free:
6587 if (list != NULL) {
6588 clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL);
6589 clist_free(list);
6590 }
6591 err:
6592 return res;
6593}
6594
6595/*
6596 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
6597 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
6598 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
6599 "BODY" section ["<" number ">"] SP nstring /
6600 "UID" SP uniqueid
6601 ; MUST NOT change for a message
6602*/
6603
6604/*
6605 "ENVELOPE" SP envelope
6606*/
6607
6608
6609static int
6610mailimap_msg_att_envelope_parse(mailstream * fd,
6611 MMAPString * buffer,
6612 size_t * index,
6613 struct mailimap_envelope ** result,
6614 size_t progr_rate,
6615 progress_function * progr_fun)
6616{
6617 size_t cur_token;
6618 struct mailimap_envelope * env;
6619 int r;
6620
6621 cur_token = * index;
6622
6623 r = mailimap_token_case_insensitive_parse(fd, buffer,
6624 &cur_token, "ENVELOPE");
6625 if (r != MAILIMAP_NO_ERROR)
6626 return r;
6627
6628 r = mailimap_space_parse(fd, buffer, &cur_token);
6629 if (r != MAILIMAP_NO_ERROR)
6630 return r;
6631
6632 r = mailimap_envelope_parse(fd, buffer, &cur_token, &env,
6633 progr_rate, progr_fun);
6634 if (r != MAILIMAP_NO_ERROR)
6635 return r;
6636
6637 * index = cur_token;
6638 * result = env;
6639
6640 return MAILIMAP_NO_ERROR;
6641}
6642
6643
6644/*
6645 "INTERNALDATE" SP date-time
6646*/
6647
6648
6649static int
6650mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer,
6651 size_t * index,
6652 struct mailimap_date_time ** result,
6653 size_t progr_rate,
6654 progress_function * progr_fun)
6655{
6656 size_t cur_token;
6657 struct mailimap_date_time * date_time;
6658 int r;
6659
6660 cur_token = * index;
6661
6662 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6663 "INTERNALDATE");
6664 if (r != MAILIMAP_NO_ERROR)
6665 return r;
6666
6667 r = mailimap_space_parse(fd, buffer, &cur_token);
6668 if (r != MAILIMAP_NO_ERROR)
6669 return FALSE;
6670
6671 r = mailimap_date_time_parse(fd, buffer, &cur_token, &date_time,
6672 progr_rate, progr_fun);
6673 if (r != MAILIMAP_NO_ERROR)
6674 return r;
6675
6676 * result = date_time;
6677 * index = cur_token;
6678
6679 return MAILIMAP_NO_ERROR;
6680}
6681
6682/*
6683 "RFC822" SP nstring
6684*/
6685
6686static int
6687mailimap_msg_att_rfc822_parse(mailstream * fd, MMAPString * buffer,
6688 size_t * index, char ** result,
6689 size_t * result_len,
6690 size_t progr_rate,
6691 progress_function * progr_fun)
6692{
6693 size_t cur_token;
6694 char * rfc822_message;
6695 int r;
6696 size_t length;
6697
6698 cur_token = * index;
6699
6700 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6701 "RFC822");
6702 if (r != MAILIMAP_NO_ERROR)
6703 return r;
6704
6705 r = mailimap_space_parse(fd, buffer, &cur_token);
6706 if (r != MAILIMAP_NO_ERROR)
6707 return r;
6708
6709 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_message, &length,
6710 progr_rate, progr_fun);
6711 if (r != MAILIMAP_NO_ERROR)
6712 return r;
6713
6714 * result = rfc822_message;
6715 if (result_len != NULL)
6716 * result_len = length;
6717 * index = cur_token;
6718
6719 return MAILIMAP_NO_ERROR;
6720}
6721
6722/*
6723 "RFC822" ".HEADER" SP nstring
6724*/
6725
6726static int
6727mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer,
6728 size_t * index, char ** result,
6729 size_t * result_len,
6730 size_t progr_rate,
6731 progress_function * progr_fun)
6732{
6733 size_t cur_token;
6734 char * rfc822_header;
6735 int r;
6736 size_t length;
6737
6738 cur_token = * index;
6739
6740 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6741 "RFC822");
6742 if (r != MAILIMAP_NO_ERROR)
6743 return r;
6744
6745 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6746 ".HEADER");
6747 if (r != MAILIMAP_NO_ERROR)
6748 return r;
6749
6750 r = mailimap_space_parse(fd, buffer, &cur_token);
6751 if (r != MAILIMAP_NO_ERROR)
6752 return r;
6753
6754 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_header, &length,
6755 progr_rate, progr_fun);
6756 if (r != MAILIMAP_NO_ERROR)
6757 return r;
6758
6759 * result = rfc822_header;
6760 if (result_len != NULL)
6761 * result_len = length;
6762 * index = cur_token;
6763
6764 return MAILIMAP_NO_ERROR;
6765}
6766
6767/*
6768 "RFC822" ".TEXT" SP nstring
6769*/
6770
6771static int
6772mailimap_msg_att_rfc822_text_parse(mailstream * fd, MMAPString * buffer,
6773 size_t * index, char ** result,
6774 size_t * result_len,
6775 size_t progr_rate,
6776 progress_function * progr_fun)
6777{
6778 size_t cur_token;
6779 char * rfc822_text;
6780 int r;
6781 size_t length;
6782
6783 cur_token = * index;
6784
6785 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6786 "RFC822");
6787 if (r != MAILIMAP_NO_ERROR)
6788 return r;
6789
6790 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6791 ".TEXT");
6792 if (r != MAILIMAP_NO_ERROR)
6793 return r;
6794
6795 r = mailimap_space_parse(fd, buffer, &cur_token);
6796 if (r != MAILIMAP_NO_ERROR)
6797 return r;
6798
6799 r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_text, &length,
6800 progr_rate, progr_fun);
6801 if (r != MAILIMAP_NO_ERROR)
6802 return r;
6803
6804 * result = rfc822_text;
6805 if (result_len != NULL)
6806 * result_len = length;
6807 * index = cur_token;
6808
6809 return MAILIMAP_NO_ERROR;
6810}
6811
6812/*
6813 "RFC822.SIZE" SP number
6814*/
6815
6816static int
6817mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer,
6818 size_t * index, uint32_t * result)
6819{
6820 size_t cur_token;
6821 uint32_t number;
6822 int r;
6823
6824 cur_token = * index;
6825
6826 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6827 "RFC822.SIZE");
6828 if (r != MAILIMAP_NO_ERROR)
6829 return r;
6830
6831 r = mailimap_space_parse(fd, buffer, &cur_token);
6832 if (r != MAILIMAP_NO_ERROR)
6833 return r;
6834
6835 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
6836 if (r != MAILIMAP_NO_ERROR)
6837 return r;
6838
6839 * result = number;
6840 * index = cur_token;
6841
6842 return MAILIMAP_NO_ERROR;
6843}
6844
6845/*
6846 "BODY" SP body
6847*/
6848
6849
6850static int
6851mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer,
6852 size_t * index, struct mailimap_body ** result,
6853 size_t progr_rate,
6854 progress_function * progr_fun)
6855{
6856 struct mailimap_body * body;
6857 size_t cur_token;
6858 int r;
6859
6860 cur_token = * index;
6861
6862 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6863 "BODY");
6864 if (r != MAILIMAP_NO_ERROR)
6865 return r;
6866
6867 r = mailimap_space_parse(fd, buffer, &cur_token);
6868 if (r != MAILIMAP_NO_ERROR)
6869 return r;
6870
6871 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
6872 progr_rate, progr_fun);
6873 if (r != MAILIMAP_NO_ERROR)
6874 return r;
6875
6876 * result = body;
6877 * index = cur_token;
6878
6879 return MAILIMAP_NO_ERROR;
6880}
6881
6882/*
6883 "BODY" "STRUCTURE" SP body
6884*/
6885
6886
6887static int
6888mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer,
6889 size_t * index,
6890 struct mailimap_body ** result,
6891 size_t progr_rate,
6892 progress_function * progr_fun)
6893{
6894 struct mailimap_body * body;
6895 size_t cur_token;
6896 int r;
6897
6898 cur_token = * index;
6899
6900 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6901 "BODY");
6902 if (r != MAILIMAP_NO_ERROR)
6903 return r;
6904
6905 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6906 "STRUCTURE");
6907 if (r != MAILIMAP_NO_ERROR)
6908 return r;
6909
6910 r = mailimap_space_parse(fd, buffer, &cur_token);
6911 if (r != MAILIMAP_NO_ERROR)
6912 return r;
6913
6914 r = mailimap_body_parse(fd, buffer, &cur_token, &body,
6915 progr_rate, progr_fun);
6916 if (r != MAILIMAP_NO_ERROR)
6917 return r;
6918
6919 * result = body;
6920 * index = cur_token;
6921
6922 return MAILIMAP_NO_ERROR;
6923}
6924
6925/*
6926 "BODY" section ["<" number ">"] SP nstring
6927*/
6928
6929static int
6930mailimap_msg_att_body_section_parse(mailstream * fd, MMAPString * buffer,
6931 size_t * index,
6932 struct mailimap_msg_att_body_section **
6933 result,
6934 size_t progr_rate,
6935 progress_function * progr_fun)
6936{
6937 size_t cur_token;
6938 uint32_t number;
6939 struct mailimap_section * section;
6940 char * body_part;
6941 struct mailimap_msg_att_body_section * msg_att_body_section;
6942 int r;
6943 int res;
6944 size_t length;
6945
6946 cur_token = * index;
6947
6948 section = NULL;
6949 number = 0;
6950 body_part = NULL;
6951
6952 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
6953 "BODY");
6954 if (r != MAILIMAP_NO_ERROR) {
6955 res = r;
6956 goto err;
6957 }
6958
6959 r = mailimap_section_parse(fd, buffer, &cur_token, &section,
6960 progr_rate, progr_fun);
6961 if (r != MAILIMAP_NO_ERROR) {
6962 res = r;
6963 goto err;
6964 }
6965
6966 r = mailimap_lower_parse(fd, buffer, &cur_token);
6967 switch (r) {
6968 case MAILIMAP_NO_ERROR:
6969 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
6970 if (r != MAILIMAP_NO_ERROR) {
6971 res = r;
6972 goto free_section;
6973 }
6974
6975 r = mailimap_greater_parse(fd, buffer, &cur_token);
6976 if (r != MAILIMAP_NO_ERROR) {
6977 res = r;
6978 goto free_section;
6979 }
6980 break;
6981
6982 case MAILIMAP_ERROR_PARSE:
6983 break;
6984
6985 default:
6986 return r;
6987 }
6988
6989 r = mailimap_space_parse(fd, buffer, &cur_token);
6990 if (r != MAILIMAP_NO_ERROR) {
6991 res = r;
6992 goto free_section;
6993 }
6994
6995 r = mailimap_nstring_parse(fd, buffer, &cur_token, &body_part, &length,
6996 progr_rate, progr_fun);
6997 if (r != MAILIMAP_NO_ERROR) {
6998 res = r;
6999 goto free_section;
7000 }
7001
7002 msg_att_body_section =
7003 mailimap_msg_att_body_section_new(section, number, body_part, length);
7004 if (msg_att_body_section == NULL) {
7005 res = MAILIMAP_ERROR_MEMORY;
7006 goto free_string;
7007 }
7008
7009 * result = msg_att_body_section;
7010 * index = cur_token;
7011
7012 return MAILIMAP_NO_ERROR;
7013
7014 free_string:
7015 mailimap_nstring_free(body_part);
7016 free_section:
7017 if (section != NULL)
7018 mailimap_section_free(section);
7019 err:
7020 return res;
7021}
7022
7023/*
7024 "UID" SP uniqueid
7025*/
7026
7027static int
7028mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer,
7029 size_t * index,
7030 uint32_t * result)
7031{
7032 size_t cur_token;
7033 uint32_t uid;
7034 int r;
7035
7036 cur_token = * index;
7037
7038 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID");
7039 if (r != MAILIMAP_NO_ERROR)
7040 return r;
7041
7042 r = mailimap_space_parse(fd, buffer, &cur_token);
7043 if (r != MAILIMAP_NO_ERROR)
7044 return r;
7045
7046 r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uid);
7047 if (r != MAILIMAP_NO_ERROR)
7048 return r;
7049
7050 * index = cur_token;
7051 * result = uid;
7052
7053 return MAILIMAP_NO_ERROR;
7054}
7055
7056/*
7057 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
7058 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
7059 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
7060 "BODY" section ["<" number ">"] SP nstring /
7061 "UID" SP uniqueid
7062 ; MUST NOT change for a message
7063*/
7064
7065static int
7066mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer,
7067 size_t * index,
7068 struct mailimap_msg_att_static ** result,
7069 size_t progr_rate,
7070 progress_function * progr_fun)
7071{
7072 size_t cur_token;
7073 struct mailimap_envelope * env;
7074 struct mailimap_date_time * internal_date;
7075 char * rfc822;
7076 char * rfc822_header;
7077 char * rfc822_text;
7078 uint32_t rfc822_size;
7079 struct mailimap_body * bodystructure;
7080 struct mailimap_body * body;
7081 struct mailimap_msg_att_body_section * body_section;
7082 uint32_t uid;
7083 struct mailimap_msg_att_static * msg_att_static;
7084 int type;
7085 int r;
7086 int res;
7087 size_t length;
7088
7089 cur_token = * index;
7090
7091 env = NULL;
7092 internal_date = NULL;
7093 rfc822 = NULL;
7094 rfc822_header = NULL;
7095 rfc822_text = NULL;
7096 rfc822_size = 0;
7097 length = 0;
7098 bodystructure = NULL;
7099 body = NULL;
7100 body_section = NULL;
7101 uid = 0;
7102
7103 type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */
7104
7105 r = mailimap_msg_att_envelope_parse(fd, buffer, &cur_token, &env,
7106 progr_rate, progr_fun);
7107 if (r == MAILIMAP_NO_ERROR)
7108 type = MAILIMAP_MSG_ATT_ENVELOPE;
7109
7110 if (r == MAILIMAP_ERROR_PARSE) {
7111 r = mailimap_msg_att_internaldate_parse(fd, buffer, &cur_token,
7112 &internal_date,
7113 progr_rate, progr_fun);
7114 if (r == MAILIMAP_NO_ERROR)
7115 type = MAILIMAP_MSG_ATT_INTERNALDATE;
7116 }
7117
7118 if (r == MAILIMAP_ERROR_PARSE) {
7119 r = mailimap_msg_att_rfc822_parse(fd, buffer, &cur_token,
7120 &rfc822, &length,
7121 progr_rate, progr_fun);
7122 if (r == MAILIMAP_NO_ERROR)
7123 type = MAILIMAP_MSG_ATT_RFC822;
7124 }
7125
7126 if (r == MAILIMAP_ERROR_PARSE) {
7127 r = mailimap_msg_att_rfc822_header_parse(fd, buffer, &cur_token,
7128 &rfc822_header, &length,
7129 progr_rate, progr_fun);
7130 type = MAILIMAP_MSG_ATT_RFC822_HEADER;
7131 }
7132
7133 if (r == MAILIMAP_ERROR_PARSE) {
7134 r = mailimap_msg_att_rfc822_text_parse(fd, buffer, &cur_token,
7135 &rfc822_text, &length,
7136 progr_rate, progr_fun);
7137 if (r == MAILIMAP_NO_ERROR)
7138 type = MAILIMAP_MSG_ATT_RFC822_TEXT;
7139 }
7140
7141 if (r == MAILIMAP_ERROR_PARSE) {
7142 r = mailimap_msg_att_rfc822_size_parse(fd, buffer, &cur_token,
7143 &rfc822_size);
7144 if (r == MAILIMAP_NO_ERROR)
7145 type = MAILIMAP_MSG_ATT_RFC822_SIZE;
7146 }
7147
7148 if (r == MAILIMAP_ERROR_PARSE) {
7149 r = mailimap_msg_att_body_parse(fd, buffer, &cur_token,
7150 &body, progr_rate, progr_fun);
7151 if (r == MAILIMAP_NO_ERROR)
7152 type = MAILIMAP_MSG_ATT_BODY;
7153 }
7154
7155 if (r == MAILIMAP_ERROR_PARSE) {
7156 r = mailimap_msg_att_bodystructure_parse(fd, buffer, &cur_token,
7157 &bodystructure,
7158 progr_rate, progr_fun);
7159 if (r == MAILIMAP_NO_ERROR)
7160 type = MAILIMAP_MSG_ATT_BODYSTRUCTURE;
7161 }
7162
7163 if (r == MAILIMAP_ERROR_PARSE) {
7164 r = mailimap_msg_att_body_section_parse(fd, buffer, &cur_token,
7165 &body_section,
7166 progr_rate, progr_fun);
7167 if (r == MAILIMAP_NO_ERROR)
7168 type = MAILIMAP_MSG_ATT_BODY_SECTION;
7169 }
7170
7171 if (r == MAILIMAP_ERROR_PARSE) {
7172 r = mailimap_msg_att_uid_parse(fd, buffer, &cur_token,
7173 &uid);
7174 if (r == MAILIMAP_NO_ERROR)
7175 type = MAILIMAP_MSG_ATT_UID;
7176 }
7177
7178 if (r != MAILIMAP_NO_ERROR) {
7179 res = r;
7180 goto err;
7181 }
7182
7183 msg_att_static = mailimap_msg_att_static_new(type, env, internal_date,
7184 rfc822, rfc822_header,
7185 rfc822_text, length,
7186 rfc822_size, bodystructure,
7187 body, body_section, uid);
7188 if (msg_att_static == NULL) {
7189 res = MAILIMAP_ERROR_MEMORY;
7190 goto free;
7191 }
7192
7193 * result = msg_att_static;
7194 * index = cur_token;
7195
7196 return MAILIMAP_NO_ERROR;
7197
7198 free:
7199 if (env)
7200 mailimap_msg_att_envelope_free(env);
7201 if (internal_date)
7202 mailimap_msg_att_internaldate_free(internal_date);
7203 if (rfc822)
7204 mailimap_msg_att_rfc822_free(rfc822);
7205 if (rfc822_header)
7206 mailimap_msg_att_rfc822_header_free(rfc822_header);
7207 if (rfc822_text)
7208 mailimap_msg_att_rfc822_text_free(rfc822_text);
7209 if (bodystructure)
7210 mailimap_msg_att_bodystructure_free(bodystructure);
7211 if (body)
7212 mailimap_msg_att_body_free(body);
7213 if (body_section)
7214 mailimap_msg_att_body_section_free(body_section);
7215 err:
7216 return res;
7217}
7218
7219
7220/*
7221 nil = "NIL"
7222*/
7223
7224static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer,
7225 size_t * index)
7226{
7227 return mailimap_token_case_insensitive_parse(fd, buffer, index, "NIL");
7228}
7229
7230/*
7231 nstring = string / nil
7232*/
7233
7234
7235static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer,
7236 size_t * index, char ** result,
7237 size_t * result_len,
7238 size_t progr_rate,
7239 progress_function * progr_fun)
7240{
7241 int r;
7242
7243 r = mailimap_string_parse(fd, buffer, index, result, result_len,
7244 progr_rate, progr_fun);
7245 switch (r) {
7246 case MAILIMAP_NO_ERROR:
7247 return MAILIMAP_NO_ERROR;
7248
7249 case MAILIMAP_ERROR_PARSE:
7250 r = mailimap_nil_parse(fd, buffer, index);
7251 if (r != MAILIMAP_NO_ERROR) {
7252 return r;
7253 }
7254
7255 * result = NULL;
7256 if (result_len != NULL)
7257 * result_len = 0;
7258 return MAILIMAP_NO_ERROR;
7259
7260 default:
7261 return r;
7262 }
7263}
7264
7265/*
7266 number = 1*DIGIT
7267 ; Unsigned 32-bit integer
7268 ; (0 <= n < 4,294,967,296)
7269*/
7270
7271static int
7272mailimap_number_parse(mailstream * fd, MMAPString * buffer,
7273 size_t * index, uint32_t * result)
7274{
7275 size_t cur_token;
7276 int digit;
7277 uint32_t number;
7278 int parsed;
7279 int r;
7280
7281 cur_token = * index;
7282 parsed = FALSE;
7283
7284#ifdef UNSTRICT_SYNTAX
7285 mailimap_space_parse(fd, buffer, &cur_token);
7286#endif
7287
7288 number = 0;
7289 while (1) {
7290 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
7291 if (r == MAILIMAP_ERROR_PARSE)
7292 break;
7293 else if (r == MAILIMAP_NO_ERROR) {
7294 number *= 10;
7295 number += digit;
7296 parsed = TRUE;
7297 }
7298 else
7299 return r;
7300 }
7301
7302 if (!parsed)
7303 return MAILIMAP_ERROR_PARSE;
7304
7305 * result = number;
7306 * index = cur_token;
7307
7308 return MAILIMAP_NO_ERROR;
7309}
7310
7311/*
7312 nz-number = digit-nz *DIGIT
7313 ; Non-zero unsigned 32-bit integer
7314 ; (0 < n < 4,294,967,296)
7315*/
7316
7317static int
7318mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer,
7319 size_t * index, uint32_t * result)
7320{
7321#ifdef UNSTRICT_SYNTAX
7322 size_t cur_token;
7323 uint32_t number;
7324 int r;
7325
7326 cur_token = * index;
7327
7328 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
7329 if (r != MAILIMAP_NO_ERROR)
7330 return r;
7331
7332 if (number == 0)
7333 return MAILIMAP_ERROR_PARSE;
7334
7335#else
7336 size_t cur_token;
7337 int digit;
7338 uint32_t number;
7339 int r;
7340
7341 cur_token = * index;
7342
7343 r = mailimap_digit_nz_parse(fd, buffer, &cur_token, &digit);
7344 if (r != MAILIMAP_NO_ERROR)
7345 return r;
7346
7347 number = digit;
7348
7349 while (1) {
7350 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
7351 if (r == MAILIMAP_ERROR_PARSE)
7352 break;
7353 else if (r == MAILIMAP_NO_ERROR) {
7354 number *= 10;
7355 number += (guint32) digit;
7356 }
7357 else
7358 return r;
7359 }
7360#endif
7361
7362 * result = number;
7363 * index = cur_token;
7364
7365 return MAILIMAP_NO_ERROR;
7366}
7367
7368/*
7369 password = astring
7370*/
7371
7372/*
7373 quoted = DQUOTE *QUOTED-CHAR DQUOTE
7374*/
7375
7376static int
7377mailimap_quoted_parse(mailstream * fd, MMAPString * buffer,
7378 size_t * index, char ** result,
7379 size_t progr_rate,
7380 progress_function * progr_fun)
7381{
7382 char ch;
7383 size_t cur_token;
7384 MMAPString * gstr_quoted;
7385 int r;
7386 int res;
7387
7388 cur_token = * index;
7389
7390#ifdef UNSTRICT_SYNTAX
7391 r = mailimap_space_parse(fd, buffer, &cur_token);
7392 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
7393 return r;
7394#endif
7395
7396 r = mailimap_dquote_parse(fd, buffer, &cur_token);
7397 if (r != MAILIMAP_NO_ERROR) {
7398 res = r;
7399 goto err;
7400 }
7401
7402 gstr_quoted = mmap_string_new("");
7403 if (gstr_quoted == NULL) {
7404 res = MAILIMAP_ERROR_MEMORY;
7405 goto err;
7406 }
7407
7408 while (1) {
7409 r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch);
7410 if (r == MAILIMAP_ERROR_PARSE)
7411 break;
7412 else if (r == MAILIMAP_NO_ERROR) {
7413 if (mmap_string_append_c(gstr_quoted, ch) == NULL) {
7414 res = MAILIMAP_ERROR_MEMORY;
7415 goto free;
7416 }
7417 }
7418 else {
7419 res = r;
7420 goto free;
7421 }
7422 }
7423
7424 r = mailimap_dquote_parse(fd, buffer, &cur_token);
7425 if (r != MAILIMAP_NO_ERROR) {
7426 res = r;
7427 goto free;
7428 }
7429
7430 if (mmap_string_ref(gstr_quoted) < 0) {
7431 res = MAILIMAP_ERROR_MEMORY;
7432 goto free;
7433 }
7434
7435 * index = cur_token;
7436 * result = gstr_quoted->str;
7437
7438 return MAILIMAP_NO_ERROR;
7439
7440 free:
7441 mmap_string_free(gstr_quoted);
7442 err:
7443 return res;
7444}
7445
7446/*
7447 QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
7448 "\" quoted-specials
7449*/
7450
7451static int is_quoted_specials(char ch);
7452
7453static int
7454mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer,
7455 size_t * index, char * result)
7456{
7457 size_t cur_token;
7458 int r;
7459
7460 cur_token = * index;
7461
7462 if (!is_quoted_specials(buffer->str[cur_token])) {
7463 * result = buffer->str[cur_token];
7464 cur_token ++;
7465 * index = cur_token;
7466 return MAILIMAP_NO_ERROR;
7467 }
7468 else {
7469 char quoted_special;
7470
7471 r = mailimap_char_parse(fd, buffer, &cur_token, '\\');
7472 if (r != MAILIMAP_NO_ERROR)
7473 return r;
7474
7475 r = mailimap_quoted_specials_parse(fd, buffer, &cur_token,
7476 &quoted_special);
7477 if (r != MAILIMAP_NO_ERROR)
7478 return r;
7479
7480 * result = quoted_special;
7481 * index = cur_token;
7482
7483 return MAILIMAP_NO_ERROR;
7484 }
7485}
7486
7487/*
7488 quoted-specials = DQUOTE / "\"
7489*/
7490
7491static int is_quoted_specials(char ch)
7492{
7493 return (ch == '\"') || (ch == '\\');
7494}
7495
7496static int
7497mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer,
7498 size_t * index, char * result)
7499{
7500 size_t cur_token;
7501
7502 cur_token = * index;
7503
7504 if (is_quoted_specials(buffer->str[cur_token])) {
7505 * result = buffer->str[cur_token];
7506 cur_token ++;
7507 * index = cur_token;
7508 return MAILIMAP_NO_ERROR;
7509 }
7510 else
7511 return MAILIMAP_ERROR_PARSE;
7512}
7513
7514/*
7515 UNIMPLEMENTED
7516 rename = "RENAME" SP mailbox SP mailbox
7517 ; Use of INBOX as a destination gives a NO error
7518*/
7519
7520/*
7521 response = *(continue-req / response-data) response-done
7522*/
7523
7524/*
7525 continue-req / response-data
7526*/
7527
7528/* static */ int
7529mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer,
7530 size_t * index,
7531 struct mailimap_cont_req_or_resp_data **
7532 result,
7533 size_t progr_rate,
7534 progress_function * progr_fun)
7535{
7536 size_t cur_token;
7537 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
7538 struct mailimap_continue_req * cont_req;
7539 struct mailimap_response_data * resp_data;
7540 int type;
7541 int r;
7542 int res;
7543
7544 cur_token = * index;
7545
7546 cont_req = NULL;
7547 resp_data = NULL;
7548 type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */
7549
7550 r = mailimap_continue_req_parse(fd, buffer, &cur_token, &cont_req,
7551 progr_rate, progr_fun);
7552 if (r == MAILIMAP_NO_ERROR)
7553 type = MAILIMAP_RESP_CONT_REQ;
7554
7555 if (r == MAILIMAP_ERROR_PARSE) {
7556 r = mailimap_response_data_parse(fd, buffer, &cur_token, &resp_data,
7557 progr_rate, progr_fun);
7558 if (r == MAILIMAP_NO_ERROR)
7559 type = MAILIMAP_RESP_RESP_DATA;
7560 }
7561
7562 if (r != MAILIMAP_NO_ERROR) {
7563 res = r;
7564 goto err;
7565 }
7566
7567 /*
7568 multi-lines response
7569 read another response line because after that token,
7570 there must have something (continue-req, response-data or response-done)
7571 */
7572
7573 if (!mailstream_read_line_append(fd, buffer)) {
7574 res = MAILIMAP_ERROR_STREAM;
7575 goto free;
7576 }
7577
7578 cont_req_or_resp_data =
7579 mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data);
7580 if (cont_req_or_resp_data == NULL) {
7581 res = MAILIMAP_ERROR_MEMORY;
7582 goto free;
7583 }
7584
7585 * result = cont_req_or_resp_data;
7586 * index = cur_token;
7587
7588 return MAILIMAP_NO_ERROR;
7589
7590 free:
7591 if (cont_req != NULL)
7592 mailimap_continue_req_free(cont_req);
7593 if (resp_data != NULL)
7594 mailimap_response_data_free(resp_data);
7595 err:
7596 return res;
7597}
7598
7599/*
7600 response = *(continue-req / response-data) response-done
7601*/
7602
7603int
7604mailimap_response_parse(mailstream * fd, MMAPString * buffer,
7605 size_t * index, struct mailimap_response ** result,
7606 size_t progr_rate,
7607 progress_function * progr_fun)
7608{
7609 size_t cur_token;
7610 clist * cont_req_or_resp_data_list;
7611 struct mailimap_response * resp;
7612 struct mailimap_response_done * resp_done;
7613 int r;
7614 int res;
7615
7616 cur_token = * index;
7617 cont_req_or_resp_data_list = NULL;
7618 resp_done = NULL;
7619
7620 r = mailimap_struct_multiple_parse(fd, buffer,
7621 &cur_token, &cont_req_or_resp_data_list,
7622 (mailimap_struct_parser *)
7623 mailimap_cont_req_or_resp_data_parse,
7624 (mailimap_struct_destructor *)
7625 mailimap_cont_req_or_resp_data_free,
7626 progr_rate, progr_fun);
7627
7628 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
7629 return r;
7630
7631 r = mailimap_response_done_parse(fd, buffer, &cur_token, &resp_done,
7632 progr_rate, progr_fun);
7633 if (r != MAILIMAP_NO_ERROR) {
7634 res = r;
7635 goto free_list;
7636 }
7637
7638 resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done);
7639 if (resp == NULL) {
7640 res = MAILIMAP_ERROR_MEMORY;
7641 goto free_resp_done;
7642 }
7643
7644 * result = resp;
7645 * index = cur_token;
7646
7647 return MAILIMAP_NO_ERROR;
7648
7649 free_resp_done:
7650 mailimap_response_done_free(resp_done);
7651 free_list:
7652 if (cont_req_or_resp_data_list != NULL) {
7653 clist_foreach(cont_req_or_resp_data_list,
7654 (clist_func) mailimap_cont_req_or_resp_data_free, NULL);
7655 clist_free(cont_req_or_resp_data_list);
7656 }
7657 return res;
7658}
7659
7660/*
7661 response-data = "*" SP (resp-cond-state / resp-cond-bye /
7662 mailbox-data / message-data / capability-data) CRLF
7663*/
7664
7665static int
7666mailimap_response_data_parse(mailstream * fd, MMAPString * buffer,
7667 size_t * index,
7668 struct mailimap_response_data ** result,
7669 size_t progr_rate,
7670 progress_function * progr_fun)
7671{
7672 struct mailimap_response_data * resp_data;
7673 size_t cur_token;
7674 int type;
7675 struct mailimap_resp_cond_state * cond_state;
7676 struct mailimap_resp_cond_bye * cond_bye;
7677 struct mailimap_mailbox_data * mb_data;
7678 struct mailimap_message_data * msg_data;
7679 struct mailimap_capability_data * cap_data;
7680 int r;
7681 int res;
7682
7683 cond_state = NULL;
7684 cond_bye = NULL;
7685 mb_data = NULL;
7686 msg_data = NULL;
7687 cap_data = NULL;
7688
7689 cur_token = * index;
7690
7691 r = mailimap_star_parse(fd, buffer, &cur_token);
7692 if (r != MAILIMAP_NO_ERROR) {
7693 res = r;
7694 goto err;
7695 }
7696
7697 r = mailimap_space_parse(fd, buffer, &cur_token);
7698 if (r != MAILIMAP_NO_ERROR) {
7699 res = r;
7700 goto err;
7701 }
7702
7703 type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */
7704
7705 r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state,
7706 progr_rate, progr_fun);
7707 if (r == MAILIMAP_NO_ERROR)
7708 type = MAILIMAP_RESP_DATA_TYPE_COND_STATE;
7709
7710 if (r == MAILIMAP_ERROR_PARSE) {
7711 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye,
7712 progr_rate, progr_fun);
7713 if (r == MAILIMAP_NO_ERROR)
7714 type = MAILIMAP_RESP_DATA_TYPE_COND_BYE;
7715 }
7716
7717 if (r == MAILIMAP_ERROR_PARSE) {
7718 r = mailimap_mailbox_data_parse(fd, buffer, &cur_token, &mb_data,
7719 progr_rate, progr_fun);
7720 if (r == MAILIMAP_NO_ERROR)
7721 type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA;
7722 }
7723
7724 if (r == MAILIMAP_ERROR_PARSE) {
7725 r = mailimap_message_data_parse(fd, buffer, &cur_token, &msg_data,
7726 progr_rate, progr_fun);
7727 if (r == MAILIMAP_NO_ERROR)
7728 type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA;
7729 }
7730
7731 if (r == MAILIMAP_ERROR_PARSE) {
7732 r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data,
7733 progr_rate, progr_fun);
7734 if (r == MAILIMAP_NO_ERROR)
7735 type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA;
7736 }
7737
7738 if (r != MAILIMAP_NO_ERROR) {
7739 res = r;
7740 goto err;
7741 }
7742
7743 r = mailimap_crlf_parse(fd, buffer, &cur_token);
7744 if (r != MAILIMAP_NO_ERROR) {
7745 res = r;
7746 goto free;
7747 }
7748
7749 resp_data = mailimap_response_data_new(type, cond_state,
7750 cond_bye, mb_data,
7751 msg_data, cap_data);
7752 if (resp_data == NULL) {
7753 res = MAILIMAP_ERROR_MEMORY;
7754 goto free;
7755 }
7756
7757 * result = resp_data;
7758 * index = cur_token;
7759
7760 return MAILIMAP_NO_ERROR;
7761
7762 free:
7763 if (cond_state)
7764 mailimap_resp_cond_state_free(cond_state);
7765 if (cond_bye)
7766 mailimap_resp_cond_bye_free(cond_bye);
7767 if (mb_data)
7768 mailimap_mailbox_data_free(mb_data);
7769 if (msg_data)
7770 mailimap_message_data_free(msg_data);
7771 if (cap_data)
7772 mailimap_capability_data_free(cap_data);
7773 err:
7774 return res;
7775}
7776
7777/*
7778 response-done = response-tagged / response-fatal
7779*/
7780
7781static int
7782mailimap_response_done_parse(mailstream * fd, MMAPString * buffer,
7783 size_t * index,
7784 struct mailimap_response_done ** result,
7785 size_t progr_rate,
7786 progress_function * progr_fun)
7787{
7788 int type;
7789 struct mailimap_response_done * resp_done;
7790 size_t cur_token;
7791 struct mailimap_response_tagged * tagged;
7792 struct mailimap_response_fatal * fatal;
7793 int r;
7794 int res;
7795
7796 cur_token = * index;
7797
7798 tagged = NULL;
7799 fatal = NULL;
7800
7801 type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */
7802
7803 r = mailimap_response_tagged_parse(fd, buffer, &cur_token, &tagged,
7804 progr_rate, progr_fun);
7805 if (r == MAILIMAP_NO_ERROR)
7806 type = MAILIMAP_RESP_DONE_TYPE_TAGGED;
7807
7808 if (r == MAILIMAP_ERROR_PARSE) {
7809 r = mailimap_response_fatal_parse(fd, buffer, &cur_token, &fatal,
7810 progr_rate, progr_fun);
7811 if (r == MAILIMAP_NO_ERROR)
7812 type = MAILIMAP_RESP_DONE_TYPE_FATAL;
7813 }
7814
7815 if (r != MAILIMAP_NO_ERROR) {
7816 res = r;
7817 goto err;
7818 }
7819
7820 resp_done = mailimap_response_done_new(type, tagged, fatal);
7821 if (resp_done == NULL) {
7822 res = MAILIMAP_ERROR_MEMORY;
7823 goto free;
7824 }
7825
7826 * result = resp_done;
7827 * index = cur_token;
7828
7829 return MAILIMAP_NO_ERROR;
7830
7831 free:
7832 if (tagged == NULL)
7833 mailimap_response_tagged_free(tagged);
7834 if (fatal == NULL)
7835 mailimap_response_fatal_free(fatal);
7836 err:
7837 return res;
7838}
7839
7840/*
7841 response-fatal = "*" SP resp-cond-bye CRLF
7842 ; Server closes connection immediately
7843*/
7844
7845static int
7846mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer,
7847 size_t * index,
7848 struct mailimap_response_fatal ** result,
7849 size_t progr_rate,
7850 progress_function * progr_fun)
7851{
7852 struct mailimap_resp_cond_bye * cond_bye;
7853 struct mailimap_response_fatal * fatal;
7854 size_t cur_token;
7855 int res;
7856 int r;
7857
7858 cur_token = * index;
7859
7860 r = mailimap_star_parse(fd, buffer, &cur_token);
7861 if (r != MAILIMAP_NO_ERROR) {
7862 res = r;
7863 goto err;
7864 }
7865
7866 r = mailimap_space_parse(fd, buffer, &cur_token);
7867 if (r != MAILIMAP_NO_ERROR) {
7868 res = r;
7869 goto err;
7870 }
7871
7872 r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye,
7873 progr_rate, progr_fun);
7874 if (r != MAILIMAP_NO_ERROR) {
7875 res = r;
7876 goto err;
7877 }
7878
7879 r = mailimap_crlf_parse(fd, buffer, &cur_token);
7880 if (r != MAILIMAP_NO_ERROR) {
7881 res = r;
7882 goto free;
7883 }
7884
7885 fatal = mailimap_response_fatal_new(cond_bye);
7886 if (fatal == NULL) {
7887 res = MAILIMAP_ERROR_MEMORY;
7888 goto free;
7889 }
7890
7891 * result = fatal;
7892 * index = cur_token;
7893
7894 return MAILIMAP_NO_ERROR;
7895
7896 free:
7897 mailimap_resp_cond_bye_free(cond_bye);
7898 err:
7899 return res;
7900}
7901
7902/*
7903 response-tagged = tag SP resp-cond-state CRLF
7904*/
7905
7906static int
7907mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer,
7908 size_t * index,
7909 struct mailimap_response_tagged ** result,
7910 size_t progr_rate,
7911 progress_function * progr_fun)
7912{
7913 size_t cur_token;
7914 char * tag;
7915 struct mailimap_resp_cond_state * cond_state;
7916 struct mailimap_response_tagged * resp_tagged;
7917 int r;
7918 int res;
7919
7920 cur_token = * index;
7921 cond_state = NULL;
7922
7923 r = mailimap_tag_parse(fd, buffer, &cur_token, &tag,
7924 progr_rate, progr_fun);
7925 if (r != MAILIMAP_NO_ERROR) {
7926 res = r;
7927 goto err;
7928 }
7929
7930 r = mailimap_space_parse(fd, buffer, &cur_token);
7931 if (r != MAILIMAP_NO_ERROR) {
7932 res = r;
7933 goto free_tag;
7934 }
7935
7936 r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state,
7937 progr_rate, progr_fun);
7938 if (r != MAILIMAP_NO_ERROR) {
7939 res = r;
7940 goto free_tag;
7941 }
7942
7943 resp_tagged = mailimap_response_tagged_new(tag, cond_state);
7944 if (resp_tagged == NULL) {
7945 res = MAILIMAP_ERROR_MEMORY;
7946 goto free_cond_state;
7947 }
7948
7949 * result = resp_tagged;
7950 * index = cur_token;
7951
7952 return MAILIMAP_NO_ERROR;
7953
7954 free_cond_state:
7955 mailimap_resp_cond_state_free(cond_state);
7956 free_tag:
7957 mailimap_tag_free(tag);
7958 err:
7959 return res;
7960}
7961
7962/*
7963 resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
7964 ; Authentication condition
7965*/
7966
7967static int
7968mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer,
7969 size_t * index,
7970 struct mailimap_resp_cond_auth ** result,
7971 size_t progr_rate,
7972 progress_function * progr_fun)
7973{
7974 struct mailimap_resp_cond_auth * cond_auth;
7975 size_t cur_token;
7976 struct mailimap_resp_text * text;
7977 int type;
7978 int r;
7979 int res;
7980
7981 cur_token = * index;
7982 text = NULL;
7983
7984 type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */
7985
7986 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK");
7987 if (r == MAILIMAP_NO_ERROR)
7988 type = MAILIMAP_RESP_COND_AUTH_OK;
7989
7990 if (r == MAILIMAP_ERROR_PARSE) {
7991 r = mailimap_token_case_insensitive_parse(fd, buffer,
7992 &cur_token, "PREAUTH");
7993 if (r == MAILIMAP_NO_ERROR)
7994 type = MAILIMAP_RESP_COND_AUTH_PREAUTH;
7995 }
7996
7997 if (r != MAILIMAP_NO_ERROR) {
7998 res = r;
7999 goto err;
8000 }
8001
8002 r = mailimap_space_parse(fd, buffer, &cur_token);
8003 if (r != MAILIMAP_NO_ERROR) {
8004 res = r;
8005 goto err;
8006 }
8007
8008 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8009 progr_rate, progr_fun);
8010 if (r != MAILIMAP_NO_ERROR) {
8011 res = r;
8012 goto err;
8013 }
8014
8015 cond_auth = mailimap_resp_cond_auth_new(type, text);
8016 if (cond_auth == NULL) {
8017 res = MAILIMAP_ERROR_MEMORY;
8018 goto free;
8019 }
8020
8021 * result = cond_auth;
8022 * index = cur_token;
8023
8024 return MAILIMAP_NO_ERROR;
8025
8026 free:
8027 mailimap_resp_text_free(text);
8028 err:
8029 return res;
8030}
8031
8032/*
8033 resp-cond-bye = "BYE" SP resp-text
8034*/
8035
8036static int
8037mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer,
8038 size_t * index,
8039 struct mailimap_resp_cond_bye ** result,
8040 size_t progr_rate,
8041 progress_function * progr_fun)
8042{
8043 size_t cur_token;
8044 struct mailimap_resp_cond_bye * cond_bye;
8045 struct mailimap_resp_text * text;
8046 int r;
8047 int res;
8048
8049 cur_token = * index;
8050
8051 r = mailimap_token_case_insensitive_parse(fd, buffer,
8052 &cur_token, "BYE");
8053 if (r != MAILIMAP_NO_ERROR) {
8054 res = r;
8055 goto err;
8056 }
8057
8058 r = mailimap_space_parse(fd, buffer, &cur_token);
8059 if (r != MAILIMAP_NO_ERROR) {
8060 res = r;
8061 goto err;
8062 }
8063
8064 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8065 progr_rate, progr_fun);
8066 if (r != MAILIMAP_NO_ERROR) {
8067 res = r;
8068 goto err;
8069 }
8070
8071 cond_bye = mailimap_resp_cond_bye_new(text);
8072 if (cond_bye == NULL) {
8073 res = MAILIMAP_ERROR_MEMORY;
8074 goto free;
8075 }
8076
8077 * index = cur_token;
8078 * result = cond_bye;
8079
8080 return MAILIMAP_NO_ERROR;
8081
8082 free:
8083 mailimap_resp_text_free(text);
8084 err:
8085 return res;
8086}
8087
8088/*
8089 resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
8090 ; Status condition
8091*/
8092
8093static int
8094mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer,
8095 size_t * index,
8096 struct mailimap_resp_cond_state ** result,
8097 size_t progr_rate,
8098 progress_function * progr_fun)
8099{
8100 struct mailimap_resp_cond_state * cond_state;
8101 size_t cur_token;
8102 struct mailimap_resp_text * text;
8103 int type;
8104 int r;
8105 int res;
8106
8107 cur_token = * index;
8108 text = NULL;
8109
8110 type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token);
8111 if (type == -1) {
8112 res = MAILIMAP_ERROR_PARSE;
8113 goto err;
8114 }
8115
8116 r = mailimap_space_parse(fd, buffer, &cur_token);
8117 if (r != MAILIMAP_NO_ERROR) {
8118 res = r;
8119 goto err;
8120 }
8121
8122 r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text,
8123 progr_rate, progr_fun);
8124 if (r != MAILIMAP_NO_ERROR) {
8125 res = r;
8126 goto err;
8127 }
8128
8129 cond_state = mailimap_resp_cond_state_new(type, text);
8130 if (cond_state == NULL) {
8131 res = MAILIMAP_ERROR_MEMORY;
8132 goto free;
8133 }
8134
8135 * result = cond_state;
8136 * index = cur_token;
8137
8138 return MAILIMAP_NO_ERROR;
8139
8140 free:
8141 mailimap_resp_text_free(text);
8142 err:
8143 return res;
8144}
8145
8146
8147/*
8148 resp-specials = "]"
8149*/
8150
8151static int is_resp_specials(char ch)
8152{
8153 switch (ch) {
8154 case ']':
8155 return TRUE;
8156 };
8157 return FALSE;
8158}
8159
8160/*
8161 resp-text = ["[" resp-text-code "]" SP] text
8162*/
8163
8164/* "[" resp-text-code "]" */
8165
8166static int
8167mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
8168 size_t * index,
8169 struct mailimap_resp_text_code **
8170 result,
8171 size_t progr_rate,
8172 progress_function * progr_fun)
8173{
8174 struct mailimap_resp_text_code * text_code;
8175 size_t cur_token;
8176 int r;
8177 int res;
8178
8179 cur_token = * index;
8180
8181 r = mailimap_obracket_parse(fd, buffer, &cur_token);
8182 if (r != MAILIMAP_NO_ERROR) {
8183 res = r;
8184 goto err;
8185 }
8186
8187 r = mailimap_resp_text_code_parse(fd, buffer, &cur_token, &text_code,
8188 progr_rate, progr_fun);
8189 if (r != MAILIMAP_NO_ERROR) {
8190 res = r;
8191 goto err;
8192 }
8193
8194 r = mailimap_cbracket_parse(fd, buffer, &cur_token);
8195 if (r != MAILIMAP_NO_ERROR) {
8196 res = r;
8197 goto free;
8198 }
8199
8200 r = mailimap_space_parse(fd, buffer, &cur_token);
8201 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8202 res = r;
8203 goto free;
8204 }
8205
8206 * result = text_code;
8207 * index = cur_token;
8208
8209 return MAILIMAP_NO_ERROR;
8210
8211 free:
8212 mailimap_resp_text_code_free(text_code);
8213 err:
8214 return res;
8215}
8216
8217/*
8218 resp-text = ["[" resp-text-code "]" SP] text
8219*/
8220
8221static int
8222mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer,
8223 size_t * index,
8224 struct mailimap_resp_text ** result,
8225 size_t progr_rate,
8226 progress_function * progr_fun)
8227{
8228 size_t cur_token;
8229 struct mailimap_resp_text_code * text_code;
8230 struct mailimap_resp_text * resp_text;
8231 char * text;
8232 int r;
8233 int res;
8234
8235 cur_token = * index;
8236 text = NULL;
8237 text_code = NULL;
8238
8239 r = mailimap_resp_text_resp_text_code_parse(fd, buffer, &cur_token,
8240 &text_code,
8241 progr_rate, progr_fun);
8242 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
8243 return r;
8244
8245 r = mailimap_text_parse(fd, buffer, &cur_token, &text,
8246 progr_rate, progr_fun);
8247 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8248 res = r;
8249 goto free_resp_text_code;
8250 }
8251
8252 resp_text = mailimap_resp_text_new(text_code, text);
8253 if (resp_text == NULL) {
8254 res = MAILIMAP_ERROR_MEMORY;
8255 goto free_text;
8256 }
8257
8258 * result = resp_text;
8259 * index = cur_token;
8260
8261 return MAILIMAP_NO_ERROR;
8262
8263 free_resp_text_code:
8264 if (text_code != NULL)
8265 mailimap_resp_text_code_free(text_code);
8266 free_text:
8267 mailimap_text_free(text);
8268 return res;
8269}
8270
8271/*
8272 resp-text-code = "ALERT" /
8273 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
8274 capability-data / "PARSE" /
8275 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
8276 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
8277 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
8278 "UNSEEN" SP nz-number /
8279 atom [SP 1*<any TEXT-CHAR except "]">]
8280*/
8281
8282/*
8283 ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE
8284*/
8285
8286static int
8287mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer,
8288 size_t * index,
8289 int * result)
8290{
8291 int id;
8292 size_t cur_token;
8293
8294 cur_token = * index;
8295
8296 id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token);
8297
8298 if (id == -1)
8299 return MAILIMAP_ERROR_PARSE;
8300
8301 * result = id;
8302 * index = cur_token;
8303
8304 return MAILIMAP_NO_ERROR;
8305}
8306
8307
8308/*
8309 "BADCHARSET" [SP "(" astring *(SP astring) ")" ]
8310*/
8311
8312/*
8313 SP "(" astring *(SP astring) ")"
8314*/
8315
8316static int
8317mailimap_resp_text_code_badcharset_1_parse(mailstream * fd,
8318 MMAPString * buffer,
8319 size_t * index,
8320 clist ** result,
8321 size_t progr_rate,
8322 progress_function * progr_fun)
8323{
8324 size_t cur_token;
8325 clist * charset;
8326 int r;
8327 int res;
8328
8329 cur_token = * index;
8330
8331 r = mailimap_space_parse(fd, buffer, &cur_token);
8332 if (r != MAILIMAP_NO_ERROR) {
8333 res = r;
8334 goto err;
8335 }
8336
8337 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
8338 if (r != MAILIMAP_NO_ERROR) {
8339 res = r;
8340 goto err;
8341 }
8342
8343 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &charset,
8344 (mailimap_struct_parser *)
8345 mailimap_astring_parse,
8346 (mailimap_struct_destructor *)
8347 mailimap_astring_free,
8348 progr_rate, progr_fun);
8349 if (r != MAILIMAP_NO_ERROR) {
8350 res = r;
8351 goto err;
8352 }
8353
8354 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
8355 if (r != MAILIMAP_NO_ERROR) {
8356 res = r;
8357 goto charset;
8358 }
8359
8360 * index = cur_token;
8361 * result = charset;
8362
8363 return MAILIMAP_NO_ERROR;
8364
8365 charset:
8366 clist_foreach(charset, (clist_func) mailimap_string_free, NULL);
8367 clist_free(charset);
8368 err:
8369 return res;
8370}
8371
8372/*
8373 "BADCHARSET" [SP "(" astring *(SP astring) ")" ]
8374*/
8375
8376static int
8377mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer,
8378 size_t * index,
8379 clist ** result,
8380 size_t progr_rate,
8381 progress_function * progr_fun)
8382{
8383 size_t cur_token;
8384 clist * charset;
8385 int r;
8386
8387 cur_token = * index;
8388
8389 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
8390 "BADCHARSET");
8391 if (r != MAILIMAP_NO_ERROR)
8392 return r;
8393
8394 charset = NULL;
8395
8396 r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, &cur_token,
8397 &charset,
8398 progr_rate, progr_fun);
8399 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE))
8400 return r;
8401
8402 * result = charset;
8403 * index = cur_token;
8404
8405 return MAILIMAP_NO_ERROR;
8406}
8407
8408/*
8409 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")"
8410*/
8411
8412static int
8413mailimap_resp_text_code_permanentflags_parse(mailstream * fd,
8414 MMAPString * buffer,
8415 size_t * index,
8416 clist ** result,
8417 size_t progr_rate,
8418 progress_function * progr_fun)
8419{
8420 size_t cur_token;
8421 clist * flaglist;
8422 int r;
8423 int res;
8424
8425 cur_token = * index;
8426
8427 flaglist = NULL;
8428
8429 r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token,
8430 "PERMANENTFLAGS");
8431 if (r != MAILIMAP_NO_ERROR) {
8432 res = r;
8433 goto err;
8434 }
8435
8436 r = mailimap_space_parse(fd, buffer, &cur_token);
8437 if (r != MAILIMAP_NO_ERROR) {
8438 res = r;
8439 goto err;
8440 }
8441
8442 r = mailimap_oparenth_parse(fd, buffer, &cur_token);
8443 if (r != MAILIMAP_NO_ERROR) {
8444 res = r;
8445 goto err;
8446 }
8447
8448 r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &flaglist,
8449 (mailimap_struct_parser *)
8450 mailimap_flag_perm_parse,
8451 (mailimap_struct_destructor *)
8452 mailimap_flag_perm_free,
8453 progr_rate, progr_fun);
8454 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8455 res = r;
8456 goto err;
8457 }
8458
8459 r = mailimap_cparenth_parse(fd, buffer, &cur_token);
8460 if (r != MAILIMAP_NO_ERROR) {
8461 res = r;
8462 goto free;
8463 }
8464
8465 * index = cur_token;
8466 * result = flaglist;
8467
8468 return MAILIMAP_NO_ERROR;
8469
8470 free:
8471 clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL);
8472 clist_free(flaglist);
8473 err:
8474 return res;
8475}
8476
8477
8478/*
8479 "UIDNEXT" SP nz-number /
8480 "UIDVALIDITY" SP nz-number /
8481 "UNSEEN" SP nz-number
8482*/
8483
8484static int
8485mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer,
8486 size_t * index,
8487 struct mailimap_resp_text_code ** result,
8488 size_t progr_rate,
8489 progress_function * progr_fun)
8490{
8491 size_t cur_token;
8492 int type;
8493 uint32_t number;
8494 struct mailimap_resp_text_code * resp_text_code;
8495 int r;
8496
8497 cur_token = * index;
8498
8499 resp_text_code = NULL;
8500
8501 type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token);
8502 if (type == -1)
8503 return MAILIMAP_ERROR_PARSE;
8504
8505 r = mailimap_space_parse(fd, buffer, &cur_token);
8506 if (r != MAILIMAP_NO_ERROR)
8507 return r;
8508
8509 r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number);
8510 if (r != MAILIMAP_NO_ERROR)
8511 return r;
8512
8513 switch (type) {
8514 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
8515 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8516 number, 0, 0, NULL , NULL);
8517 break;
8518 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
8519 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8520 0, number, 0, NULL , NULL);
8521 break;
8522 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
8523 resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL,
8524 0, 0, number, NULL , NULL);
8525 break;
8526 }
8527
8528 if (resp_text_code == NULL)
8529 return MAILIMAP_ERROR_MEMORY;
8530
8531 * result = resp_text_code;
8532 * index = cur_token;
8533
8534 return MAILIMAP_NO_ERROR;
8535}
8536
8537/*
8538 atom [SP 1*<any TEXT-CHAR except "]">]
8539*/
8540
8541static int is_text_char(char ch);
8542
8543/*
8544 any TEXT-CHAR except "]"
8545*/
8546
8547static int is_text_char_1(char ch)
8548{
8549 if (ch == ']')
8550 return FALSE;
8551 return is_text_char(ch);
8552}
8553
8554/*
8555 1*<any TEXT-CHAR except "]"
8556*/
8557
8558static int
8559mailimap_resp_text_code_other_2_parse(mailstream * fd, MMAPString * buffer,
8560 size_t * index, char ** result,
8561 size_t progr_rate,
8562 progress_function * progr_fun)
8563{
8564 return mailimap_custom_string_parse(fd, buffer, index, result,
8565 is_text_char_1);
8566}
8567
8568/*
8569 SP 1*<any TEXT-CHAR except "]">
8570*/
8571
8572static int
8573mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer,
8574 size_t * index,
8575 char ** result,
8576 size_t progr_rate,
8577 progress_function * progr_fun)
8578{
8579 size_t cur_token;
8580 char * value;
8581 int r;
8582
8583 cur_token = * index;
8584
8585 r = mailimap_space_parse(fd, buffer, &cur_token);
8586 if (r != MAILIMAP_NO_ERROR)
8587 return r;
8588
8589 r = mailimap_resp_text_code_other_2_parse(fd, buffer, &cur_token,
8590 &value,
8591 progr_rate, progr_fun);
8592 if (r != MAILIMAP_NO_ERROR)
8593 return r;
8594
8595 * result = value;
8596 * index = cur_token;
8597
8598 return MAILIMAP_NO_ERROR;
8599}
8600
8601/*
8602 atom [SP 1*<any TEXT-CHAR except "]">]
8603*/
8604
8605static int
8606mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer,
8607 size_t * index,
8608 struct mailimap_resp_text_code ** result,
8609 size_t progr_rate,
8610 progress_function * progr_fun)
8611{
8612 size_t cur_token;
8613 char * atom;
8614 char * value;
8615 struct mailimap_resp_text_code * resp_text_code;
8616 int r;
8617 int res;
8618
8619 cur_token = * index;
8620 atom = NULL;
8621 value = NULL;
8622
8623 r = mailimap_atom_parse(fd, buffer, &cur_token, &atom,
8624 progr_rate, progr_fun);
8625 if (r != MAILIMAP_NO_ERROR) {
8626 res = r;
8627 goto err;
8628 }
8629
8630 r = mailimap_resp_text_code_other_1_parse(fd, buffer, &cur_token,
8631 &value, progr_rate, progr_fun);
8632 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8633 res = r;
8634 goto err;
8635 }
8636
8637 resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER,
8638 NULL, NULL, NULL,
8639 0, 0, 0, atom, value);
8640 if (resp_text_code == NULL) {
8641 res = MAILIMAP_ERROR_MEMORY;
8642 goto free_value;
8643 }
8644
8645 * result = resp_text_code;
8646 * index = cur_token;
8647
8648 return MAILIMAP_NO_ERROR;
8649
8650 free_value:
8651 if (value != NULL)
8652 free(value);
8653 mailimap_atom_free(atom);
8654 err:
8655 return res;
8656}
8657
8658
8659
8660/*
8661 resp-text-code = "ALERT" /
8662 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
8663 capability-data / "PARSE" /
8664 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
8665 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
8666 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
8667 "UNSEEN" SP nz-number /
8668 atom [SP 1*<any TEXT-CHAR except "]">]
8669*/
8670
8671static int
8672mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer,
8673 size_t * index,
8674 struct mailimap_resp_text_code ** result,
8675 size_t progr_rate,
8676 progress_function * progr_fun)
8677{
8678 size_t cur_token;
8679 struct mailimap_resp_text_code * resp_text_code;
8680 clist * badcharset;
8681 clist * permanentflags;
8682 struct mailimap_capability_data * cap_data;
8683 int type;
8684 int r;
8685 int res;
8686
8687 cur_token = * index;
8688
8689 resp_text_code = NULL;
8690 badcharset = NULL;
8691 cap_data = NULL;
8692 permanentflags = NULL;
8693
8694 r = mailimap_resp_text_code_1_parse(fd, buffer, &cur_token, &type);
8695 if (r == MAILIMAP_NO_ERROR) {
8696 /* do nothing */
8697 }
8698
8699 if (r == MAILIMAP_ERROR_PARSE) {
8700
8701 r = mailimap_resp_text_code_badcharset_parse(fd, buffer, &cur_token,
8702 &badcharset,
8703 progr_rate, progr_fun);
8704 if (r == MAILIMAP_NO_ERROR)
8705 type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET;
8706 }
8707
8708 if (r == MAILIMAP_ERROR_PARSE) {
8709
8710 r = mailimap_capability_data_parse(fd, buffer, &cur_token,
8711 &cap_data,
8712 progr_rate, progr_fun);
8713 if (r == MAILIMAP_NO_ERROR)
8714 type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA;
8715 }
8716
8717 if (r == MAILIMAP_ERROR_PARSE) {
8718 r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, &cur_token,
8719 &permanentflags,
8720 progr_rate,
8721 progr_fun);
8722 if (r == MAILIMAP_NO_ERROR)
8723 type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS;
8724 }
8725
8726 if (r == MAILIMAP_ERROR_PARSE) {
8727 r = mailimap_resp_text_code_number_parse(fd, buffer, &cur_token,
8728 &resp_text_code,
8729 progr_rate, progr_fun);
8730 }
8731
8732 if (r == MAILIMAP_ERROR_PARSE) {
8733 r = mailimap_resp_text_code_other_parse(fd, buffer, &cur_token,
8734 &resp_text_code,
8735 progr_rate, progr_fun);
8736 }
8737
8738 if (r != MAILIMAP_NO_ERROR) {
8739 res = r;
8740 goto err;
8741 }
8742
8743 if (resp_text_code == NULL) {
8744 resp_text_code = mailimap_resp_text_code_new(type,
8745 badcharset, cap_data,
8746 permanentflags,
8747 0, 0, 0, NULL, NULL);
8748 if (resp_text_code == NULL) {
8749 res = MAILIMAP_ERROR_MEMORY;
8750 goto free;
8751 }
8752 }
8753
8754 * result = resp_text_code;
8755 * index = cur_token;
8756
8757 return MAILIMAP_NO_ERROR;
8758
8759free:
8760 if (permanentflags) {
8761 clist_foreach(permanentflags,
8762 (clist_func) mailimap_flag_perm_free, NULL);
8763 clist_free(permanentflags);
8764 }
8765 if (cap_data)
8766 mailimap_capability_data_free(cap_data);
8767 if (badcharset) {
8768 clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL);
8769 clist_free(badcharset);
8770 }
8771err:
8772 return res;
8773}
8774
8775/*
8776 UNIMPLEMENTED
8777 search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
8778 ; CHARSET argument to MUST be registered with IANA
8779*/
8780
8781/*
8782 UNIMPLEMENTED
8783 search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
8784 "BEFORE" SP date / "BODY" SP astring /
8785 "CC" SP astring / "DELETED" / "FLAGGED" /
8786 "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" /
8787 "OLD" / "ON" SP date / "RECENT" / "SEEN" /
8788 "SINCE" SP date / "SUBJECT" SP astring /
8789 "TEXT" SP astring / "TO" SP astring /
8790 "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
8791 "UNKEYWORD" SP flag-keyword / "UNSEEN" /
8792 ; Above this line were in [IMAP2]
8793 "DRAFT" / "HEADER" SP header-fld-name SP astring /
8794 "LARGER" SP number / "NOT" SP search-key /
8795 "OR" SP search-key SP search-key /
8796 "SENTBEFORE" SP date / "SENTON" SP date /
8797 "SENTSINCE" SP date / "SMALLER" SP number /
8798 "UID" SP set / "UNDRAFT" / set /
8799 "(" search-key *(SP search-key) ")"
8800*/
8801
8802/*
8803 section = "[" [section-spec] "]"
8804*/
8805
8806static int
8807mailimap_section_parse(mailstream * fd, MMAPString * buffer,
8808 size_t * index,
8809 struct mailimap_section ** result,
8810 size_t progr_rate,
8811 progress_function * progr_fun)
8812{
8813 struct mailimap_section_spec * section_spec;
8814 size_t cur_token;
8815 struct mailimap_section * section;
8816 int r;
8817 int res;
8818
8819 cur_token = * index;
8820
8821 section_spec = NULL;
8822
8823 r = mailimap_obracket_parse(fd, buffer, &cur_token);
8824 if (r != MAILIMAP_NO_ERROR) {
8825 res = r;
8826 goto err;
8827 }
8828
8829 r = mailimap_section_spec_parse(fd, buffer, &cur_token, &section_spec,
8830 progr_rate, progr_fun);
8831 if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) {
8832 res = r;
8833 goto err;
8834 }
8835
8836 r = mailimap_cbracket_parse(fd, buffer, &cur_token);
8837 if (r != MAILIMAP_NO_ERROR) {
8838 res = r;
8839 goto err;
8840 }
8841
8842 if (section_spec == NULL)
8843 section = NULL;
8844 else {
8845 section = mailimap_section_new(section_spec);
8846 if (section == NULL) {
8847 res = MAILIMAP_ERROR_MEMORY;
8848 goto free;
8849 }
8850 }
8851
8852 * result = section;
8853 * index = cur_token;
8854
8855 return MAILIMAP_NO_ERROR;
8856
8857 free:
8858 mailimap_section_spec_free(section_spec);
8859 err:
8860 return res;
8861}
8862
8863/*
8864 section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
8865 "TEXT"
8866 ; top-level or MESSAGE/RFC822 part
8867*/
8868
8869static int
8870mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer,
8871 size_t * index,
8872 struct mailimap_section_msgtext ** result,
8873 size_t progr_rate,
8874 progress_function * progr_fun)
8875{
8876 size_t cur_token;
8877 int type;
8878 struct mailimap_header_list * header_list;
8879 struct mailimap_section_msgtext * msgtext;
8880 int r;
8881 int res;
8882
8883 cur_token = * index;
8884
8885 header_list = NULL;
8886
8887 type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token);
8888 if (type == -1) {
8889 res = MAILIMAP_ERROR_PARSE;
8890 goto err;
8891 }
8892
8893 if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) {
8894 r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list,
8895 progr_rate, progr_fun);
8896 if (r != MAILIMAP_NO_ERROR) {
8897 res = r;
8898 goto err;
8899 }
8900 }
8901 else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) {
8902 r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list,
8903 progr_rate, progr_fun);
8904 if (r != MAILIMAP_NO_ERROR) {
8905 res = r;
8906 goto err;
8907 }
8908 }
8909
8910 msgtext = mailimap_section_msgtext_new(type, header_list);
8911 if (msgtext == NULL) {
8912 res = MAILIMAP_ERROR_MEMORY;
8913 goto free_header_list;
8914 }
8915
8916 * result = msgtext;
8917 * index = cur_token;
8918
8919 return MAILIMAP_NO_ERROR;
8920
8921 free_header_list:
8922 if (header_list)
8923 mailimap_header_list_free(header_list);
8924 err:
8925 return res;
8926}
8927
8928/*
8929 section-part = nz-number *("." nz-number)
8930 ; body part nesting
8931*/
8932
8933static int
8934mailimap_section_part_parse(mailstream * fd, MMAPString * buffer,
8935 size_t * index,
8936 struct mailimap_section_part ** result,
8937 size_t progr_rate,
8938 progress_function * progr_fun)
8939{
8940 struct mailimap_section_part * section_part;
8941 size_t cur_token;
8942 clist * section_id;
8943 int r;
8944 int res;
8945
8946 cur_token = * index;
8947 section_id = NULL;
8948
8949 r = mailimap_struct_list_parse(fd, buffer, &cur_token, &section_id, '.',
8950 (mailimap_struct_parser *)
8951 mailimap_nz_number_alloc_parse,
8952 (mailimap_struct_destructor *)
8953 mailimap_number_alloc_free,
8954 progr_rate, progr_fun);
8955 if (r != MAILIMAP_NO_ERROR) {
8956 res = r;
8957 goto err;
8958 }
8959
8960 section_part = mailimap_section_part_new(section_id);
8961 if (section_part == NULL) {
8962 res = MAILIMAP_ERROR_MEMORY;
8963 goto free_section_id;
8964 }
8965
8966 * result = section_part;
8967 * index = cur_token;
8968
8969 return MAILIMAP_NO_ERROR;
8970
8971 free_section_id:
8972 clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL);
8973 clist_free(section_id);
8974 err:
8975 return res;
8976}
8977
8978/*
8979 section-spec = section-msgtext / (section-part ["." section-text])
8980*/
8981
8982static int
8983mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer,
8984 size_t * index,
8985 struct mailimap_section_spec ** result,
8986 size_t progr_rate,
8987 progress_function * progr_fun)
8988{
8989 int type;
8990 struct mailimap_section_msgtext * section_msgtext;
8991 struct mailimap_section_part * section_part;
8992 struct mailimap_section_text * section_text;
8993 struct mailimap_section_spec * section_spec;
8994 size_t cur_token;
8995 int r;
8996 int res;
8997 size_t final_token;
8998
8999 cur_token = * index;
9000
9001 section_msgtext = NULL;
9002 section_part = NULL;
9003 section_text = NULL;
9004
9005 r = mailimap_section_msgtext_parse(fd, buffer, &cur_token,
9006 &section_msgtext,
9007 progr_rate, progr_fun);
9008 switch (r) {
9009 case MAILIMAP_NO_ERROR:
9010 type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT;
9011 break;
9012
9013 case MAILIMAP_ERROR_PARSE:
9014
9015 r = mailimap_section_part_parse(fd, buffer, &cur_token,
9016 &section_part,
9017 progr_rate, progr_fun);
9018 if (r != MAILIMAP_NO_ERROR) {
9019 res = r;
9020 goto err;
9021 }
9022
9023 final_token = cur_token;
9024
9025 type = MAILIMAP_SECTION_SPEC_SECTION_PART;
9026
9027 r = mailimap_dot_parse(fd, buffer, &cur_token);
9028 if (r == MAILIMAP_NO_ERROR) {
9029 r = mailimap_section_text_parse(fd, buffer, &cur_token, &section_text,
9030 progr_rate, progr_fun);
9031 if (r == MAILIMAP_NO_ERROR) {
9032 final_token = cur_token;
9033 }
9034 else if (r != MAILIMAP_ERROR_PARSE) {
9035 res = r;
9036 goto err;
9037 }
9038 }
9039 else if (r != MAILIMAP_ERROR_PARSE) {
9040 res = r;
9041 goto err;
9042 }
9043
9044 cur_token = final_token;
9045 break;
9046
9047 default:
9048 res = r;
9049 goto err;
9050 }
9051
9052 section_spec = mailimap_section_spec_new(type, section_msgtext,
9053 section_part, section_text);
9054 if (section_spec == NULL) {
9055 res = MAILIMAP_ERROR_MEMORY;
9056 goto free;
9057 }
9058
9059 * result = section_spec;
9060 * index = cur_token;
9061
9062 return MAILIMAP_NO_ERROR;
9063
9064 free:
9065 if (section_msgtext)
9066 mailimap_section_msgtext_free(section_msgtext);
9067 if (section_part)
9068 mailimap_section_part_free(section_part);
9069 if (section_text)
9070 mailimap_section_text_free(section_text);
9071 err:
9072 return res;
9073}
9074
9075/*
9076 section-text = section-msgtext / "MIME"
9077 ; text other than actual body part (headers, etc.)
9078*/
9079
9080static int
9081mailimap_section_text_parse(mailstream * fd, MMAPString * buffer,
9082 size_t * index,
9083 struct mailimap_section_text ** result,
9084 size_t progr_rate,
9085 progress_function * progr_fun)
9086{
9087 struct mailimap_section_msgtext * section_msgtext;
9088 size_t cur_token;
9089 struct mailimap_section_text * section_text;
9090 int type;
9091 int r;
9092 int res;
9093
9094 cur_token = * index;
9095
9096 section_msgtext = NULL;
9097
9098 type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */
9099
9100 r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, &section_msgtext,
9101 progr_rate, progr_fun);
9102 if (r == MAILIMAP_NO_ERROR)
9103 type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT;
9104
9105 if (r == MAILIMAP_ERROR_PARSE) {
9106 r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME");
9107
9108 if (r == MAILIMAP_NO_ERROR)
9109 type = MAILIMAP_SECTION_TEXT_MIME;
9110 }
9111
9112 if (r != MAILIMAP_NO_ERROR) {
9113 res = r;
9114 goto err;
9115 }
9116
9117 section_text = mailimap_section_text_new(type, section_msgtext);
9118 if (section_text == NULL) {
9119 res = MAILIMAP_ERROR_MEMORY;
9120 goto free;
9121 }
9122
9123 * result = section_text;
9124 * index = cur_token;
9125
9126 return MAILIMAP_NO_ERROR;
9127
9128 free:
9129 if (section_msgtext)
9130 mailimap_section_msgtext_free(section_msgtext);
9131 err:
9132 return res;
9133}
9134
9135/*
9136 UNIMPLEMENTED
9137 select = "SELECT" SP mailbox
9138*/
9139
9140/*
9141 UNIMPLEMENTED
9142 sequence-num = nz-number / "*"
9143 ; * is the largest number in use. For message
9144 ; sequence numbers, it is the number of messages
9145 ; in the mailbox. For unique identifiers, it is
9146 ; the unique identifier of the last message in
9147 ; the mailbox.
9148*/
9149
9150/*
9151 UNIMPLEMENTED
9152 set = sequence-num / (sequence-num ":" sequence-num) /
9153 (set "," set)
9154 ; Identifies a set of messages. For message
9155 ; sequence numbers, these are consecutive
9156 ; numbers from 1 to the number of messages in
9157 ; the mailbox
9158 ; Comma delimits individual numbers, colon
9159 ; delimits between two numbers inclusive.
9160 ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
9161 ; 14,15 for a mailbox with 15 messages.
9162*/
9163
9164/*
9165 UNIMPLEMENTED
9166 status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
9167*/
9168
9169/*
9170 status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
9171 "UNSEEN"
9172*/
9173
9174static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer,
9175 size_t * index, int * result)
9176{
9177 int type;
9178 size_t cur_token;
9179
9180 cur_token = * index;
9181
9182 type = mailimap_status_att_get_token_value(fd, buffer, &cur_token);
9183
9184 if (type == -1)
9185 return MAILIMAP_ERROR_PARSE;
9186
9187 * result = type;
9188 * index = cur_token;
9189
9190 return MAILIMAP_NO_ERROR;
9191}
9192
9193
9194/*
9195 UNIMPLEMENTED
9196 store = "STORE" SP set SP store-att-flags
9197*/
9198
9199/*
9200 UNIMPLEMENTED
9201 store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
9202 (flag-list / (flag *(SP flag)))
9203*/
9204
9205/*
9206 string = quoted / literal
9207*/
9208
9209static int
9210mailimap_string_parse(mailstream * fd, MMAPString * buffer,
9211 size_t * index, char ** result,
9212 size_t * result_len,
9213 size_t progr_rate,
9214 progress_function * progr_fun)
9215{
9216 size_t cur_token;
9217 char * string;
9218 int r;
9219 size_t len;
9220
9221 cur_token = * index;
9222
9223 r = mailimap_quoted_parse(fd, buffer, &cur_token, &string,
9224 progr_rate, progr_fun);
9225 if (r == MAILIMAP_NO_ERROR)
9226 len = strlen(string);
9227 else if (r == MAILIMAP_ERROR_PARSE) {
9228 r = mailimap_literal_parse(fd, buffer, &cur_token, &string, &len,
9229 progr_rate, progr_fun);
9230 }
9231
9232 if (r != MAILIMAP_NO_ERROR)
9233 return r;
9234
9235 * result = string;
9236 if (result_len != NULL)
9237 * result_len = len;
9238 * index = cur_token;
9239
9240 return MAILIMAP_NO_ERROR;
9241}
9242
9243
9244/*
9245 UNIMPLEMENTED
9246 subscribe = "SUBSCRIBE" SP mailbox
9247*/
9248
9249/*
9250 tag = 1*<any ASTRING-CHAR except "+">
9251*/
9252
9253/*
9254 any ASTRING-CHAR except "+"
9255*/
9256
9257static int is_tag_char(char ch)
9258{
9259 if (ch == '+')
9260 return FALSE;
9261 return is_astring_char(ch);
9262}
9263
9264/*
9265 tag = 1*<any ASTRING-CHAR except "+">
9266*/
9267
9268static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer,
9269 size_t * index, char ** result,
9270 size_t progr_rate,
9271 progress_function * progr_fun)
9272{
9273 size_t cur_token;
9274 char * tag;
9275 int r;
9276
9277 cur_token = * index;
9278
9279 r = mailimap_custom_string_parse(fd, buffer, &cur_token, &tag,
9280 is_tag_char);
9281 if (r != MAILIMAP_NO_ERROR)
9282 return r;
9283
9284 * index = cur_token;
9285 * result = tag;
9286
9287 return MAILIMAP_NO_ERROR;
9288}
9289
9290/*
9291 text = 1*TEXT-CHAR
9292*/
9293
9294static int mailimap_text_parse(mailstream * fd, MMAPString * buffer,
9295 size_t * index, char ** result,
9296 size_t progr_rate,
9297 progress_function * progr_fun)
9298{
9299 return mailimap_custom_string_parse(fd, buffer, index, result,
9300 is_text_char);
9301}
9302
9303
9304/*
9305 TEXT-CHAR = <any CHAR except CR and LF>
9306*/
9307
9308static int is_text_char(char ch)
9309{
9310 if ((ch == '\r') || (ch == '\n'))
9311 return FALSE;
9312
9313 return is_char(ch);
9314}
9315
9316/*
9317 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
9318 ; Hours minutes seconds
9319*/
9320
9321/*
9322 2DIGIT
9323*/
9324
9325static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer,
9326 size_t * index, int * result)
9327{
9328#ifndef UNSTRICT_SYNTAX
9329 int digit;
9330 int two_digit;
9331 size_t cur_token;
9332 int r;
9333
9334 cur_token = * index;
9335
9336 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9337 if (r != MAILIMAP_NO_ERROR)
9338 return r;
9339
9340 two_digit = digit;
9341
9342 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9343 if (r != MAILIMAP_NO_ERROR)
9344 return r;
9345
9346 two_digit = two_digit * 10 + digit;
9347
9348 * result = two_digit;
9349 * index = cur_token;
9350
9351 return MAILIMAP_NO_ERROR;
9352#else
9353 uint32_t number;
9354 size_t cur_token;
9355 int r;
9356
9357 cur_token = * index;
9358
9359 r = mailimap_number_parse(fd, buffer, &cur_token, &number);
9360 if (r != MAILIMAP_NO_ERROR)
9361 return r;
9362
9363 * index = cur_token;
9364 * result = number;
9365
9366 return MAILIMAP_NO_ERROR;
9367#endif
9368}
9369
9370/*
9371 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
9372 ; Hours minutes seconds
9373*/
9374
9375static int mailimap_time_parse(mailstream * fd, MMAPString * buffer,
9376 size_t * index,
9377 int * phour, int * pmin, int * psec)
9378{
9379 size_t cur_token;
9380 int hour;
9381 int min;
9382 int sec;
9383 int r;
9384
9385 cur_token = * index;
9386
9387 r = mailimap_2digit_parse(fd, buffer, &cur_token, &hour);
9388 if (r != MAILIMAP_NO_ERROR)
9389 return r;
9390
9391 r = mailimap_colon_parse(fd, buffer, &cur_token);
9392 if (r != MAILIMAP_NO_ERROR)
9393 return r;
9394
9395 r = mailimap_2digit_parse(fd, buffer, &cur_token, &min);
9396 if (r != MAILIMAP_NO_ERROR)
9397 return r;
9398
9399 r = mailimap_colon_parse(fd, buffer, &cur_token);
9400 if (r != MAILIMAP_NO_ERROR)
9401 return r;
9402
9403 r = mailimap_2digit_parse(fd, buffer, &cur_token, &sec);
9404 if (r != MAILIMAP_NO_ERROR)
9405 return r;
9406
9407 * phour = hour;
9408 * pmin = min;
9409 * psec = sec;
9410 * index = cur_token;
9411
9412 return MAILIMAP_NO_ERROR;
9413}
9414
9415/*
9416 UNIMPLEMENTED
9417 uid = "UID" SP (copy / fetch / search / store)
9418 ; Unique identifiers used instead of message
9419 ; sequence numbers
9420*/
9421
9422/*
9423 uniqueid = nz-number
9424 ; Strictly ascending
9425*/
9426
9427static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer,
9428 size_t * index, uint32_t * result)
9429{
9430 return mailimap_nz_number_parse(fd, buffer, index, result);
9431}
9432
9433/*
9434 UNIMPLEMENTED
9435 unsubscribe = "UNSUBSCRIBE" SP mailbox
9436*/
9437
9438/*
9439 UNIMPLEMENTED
9440 userid = astring
9441*/
9442
9443/*
9444 UNIMPLEMENTED
9445 x-command = "X" atom <experimental command arguments>
9446*/
9447
9448/*
9449 zone = ("+" / "-") 4DIGIT
9450 ; Signed four-digit value of hhmm representing
9451 ; hours and minutes east of Greenwich (that is,
9452 ; the amount that the given time differs from
9453 ; Universal Time). Subtracting the timezone
9454 ; from the given time will give the UT form.
9455 ; The Universal Time zone is "+0000".
9456*/
9457
9458static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer,
9459 size_t * index, int * result)
9460{
9461 size_t cur_token;
9462 uint32_t zone;
9463#ifndef UNSTRICT_SYNTAX
9464 int i;
9465 int digit;
9466#endif
9467 int sign;
9468 int r;
9469
9470 cur_token = * index;
9471
9472 sign = 1;
9473 r = mailimap_plus_parse(fd, buffer, &cur_token);
9474 if (r == MAILIMAP_NO_ERROR)
9475 sign = 1;
9476
9477 if (r == MAILIMAP_ERROR_PARSE) {
9478 r = mailimap_minus_parse(fd, buffer, &cur_token);
9479 if (r == MAILIMAP_NO_ERROR)
9480 sign = -1;
9481 }
9482
9483 if (r != MAILIMAP_NO_ERROR)
9484 return r;
9485
9486#ifdef UNSTRICT_SYNTAX
9487 r = mailimap_number_parse(fd, buffer, &cur_token, &zone);
9488 if (r != MAILIMAP_NO_ERROR)
9489 return r;
9490#else
9491 zone = 0;
9492 for(i = 0 ; i < 4 ; i ++) {
9493 r = mailimap_digit_parse(fd, buffer, &cur_token, &digit);
9494 if (r != MAILIMAP_NO_ERROR)
9495 return r;
9496 zone = zone * 10 + digit;
9497 }
9498#endif
9499
9500 zone *= sign;
9501
9502 * result = zone;
9503 * index = cur_token;
9504
9505 return MAILIMAP_NO_ERROR;
9506}
diff --git a/libetpan/src/low-level/imap/mailimap_parser.h b/libetpan/src/low-level/imap/mailimap_parser.h
new file mode 100644
index 0000000..e20a310
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_parser.h
@@ -0,0 +1,69 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_PARSER_H
37
38#define MAILIMAP_PARSER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailimap_types.h"
45
46int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer,
47 size_t * index,
48 struct mailimap_greeting ** result,
49 size_t progr_rate,
50 progress_function * progr_fun);
51
52int
53mailimap_response_parse(mailstream * fd, MMAPString * buffer,
54 size_t * index, struct mailimap_response ** result,
55 size_t progr_rate,
56 progress_function * progr_fun);
57
58int
59mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer,
60 size_t * index,
61 struct mailimap_continue_req ** result,
62 size_t progr_rate,
63 progress_function * progr_fun);
64
65#ifdef __cplusplus
66}
67#endif
68
69#endif
diff --git a/libetpan/src/low-level/imap/mailimap_print.c b/libetpan/src/low-level/imap/mailimap_print.c
new file mode 100644
index 0000000..005cf09
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_print.c
@@ -0,0 +1,1615 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35#ifdef DEBUG
36#include "mailimap_print.h"
37
38#include <stdio.h>
39
40static void mailimap_body_fields_print(struct mailimap_body_fields *
41 body_fields);
42static void mailimap_envelope_print(struct mailimap_envelope * env);
43static void mailimap_body_print(struct mailimap_body * body);
44static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc *
45 fld_enc);
46
47static int indent_size = 0;
48
49static void indent()
50{
51 indent_size ++;
52}
53
54static void unindent()
55{
56 indent_size --;
57}
58
59static void print_indent()
60{
61 int i;
62
63 for (i = 0 ; i < indent_size ; i++)
64 printf(" ");
65}
66
67
68static void mailimap_body_fld_lang_print(struct mailimap_body_fld_lang *
69 fld_lang)
70{
71 clistiter * cur;
72
73 print_indent();
74 printf("body-fld-lang { ");
75
76 switch (fld_lang->lg_type) {
77 case MAILIMAP_BODY_FLD_LANG_SINGLE:
78 printf("%s ", fld_lang->lg_data.lg_single);
79 break;
80
81 case MAILIMAP_BODY_FLD_LANG_LIST:
82 for(cur = clist_begin(fld_lang->lg_data.lg_list) ;
83 cur != NULL ; cur = clist_next(cur)) {
84 char * lang;
85
86 lang = clist_content(cur);
87
88 printf("%s ", lang);
89 }
90 break;
91 }
92
93 print_indent();
94 printf("}\n");
95}
96
97static void
98mailimap_single_body_fld_param_print(struct mailimap_single_body_fld_param *
99 single)
100{
101 printf("(%s = %s)", single->pa_name, single->pa_value);
102}
103
104static void mailimap_body_fld_param_print(struct mailimap_body_fld_param *
105 fld_param)
106{
107 clistiter * cur;
108
109 print_indent();
110 printf("body-fld-param { ");
111
112 for(cur = clist_begin(fld_param->pa_list) ; cur != NULL ;
113 cur = clist_next(cur)) {
114 struct mailimap_single_body_fld_param * single;
115
116 single = clist_content(cur);
117
118 mailimap_single_body_fld_param_print(single);
119 printf(" ");
120 }
121 printf("\n");
122}
123
124static void mailimap_body_fld_dsp_print(struct mailimap_body_fld_dsp * fld_dsp)
125{
126 print_indent();
127 printf("body-fld-dsp {\n");
128 indent();
129
130 print_indent();
131 printf("name { %s }\n", fld_dsp->dsp_type);
132
133 mailimap_body_fld_param_print(fld_dsp->dsp_attributes);
134
135 unindent();
136 print_indent();
137 printf("}\n");
138}
139
140static void mailimap_body_extension_list_print(clist * ext_list);
141
142static void mailimap_body_extension_print(struct mailimap_body_extension * ext)
143{
144 print_indent();
145 printf("body-extention {\n");
146 indent();
147
148 switch (ext->ext_type) {
149 case MAILIMAP_BODY_EXTENSION_NSTRING:
150 print_indent();
151 printf("%s\n", ext->ext_data.ext_nstring);
152 break;
153 case MAILIMAP_BODY_EXTENSION_NUMBER:
154 print_indent();
155 printf("%i\n", ext->ext_data.ext_number);
156 break;
157 case MAILIMAP_BODY_EXTENSION_LIST:
158 mailimap_body_extension_list_print(ext->ext_data.ext_body_extension_list);
159 break;
160 }
161
162 unindent();
163 print_indent();
164 printf("}\n");
165
166}
167
168static void mailimap_body_extension_list_print(clist * ext_list)
169{
170 clistiter * cur;
171
172 print_indent();
173 printf("body-extention-list {\n");
174 indent();
175
176 for (cur = clist_begin(ext_list) ; cur != NULL ;
177 cur = clist_next(cur)) {
178 struct mailimap_body_extension * ext;
179
180 ext = clist_content(cur);
181
182 mailimap_body_extension_print(ext);
183 }
184
185 unindent();
186 print_indent();
187 printf("}");
188}
189
190static void mailimap_body_ext_1part_print(struct mailimap_body_ext_1part *
191 body_ext_1part)
192{
193 print_indent();
194 printf("body-type-1part {\n");
195 indent();
196
197 print_indent();
198 printf("md5 { %s }\n", body_ext_1part->bd_md5);
199 if (body_ext_1part->bd_disposition) {
200 mailimap_body_fld_dsp_print(body_ext_1part->bd_disposition);
201 if (body_ext_1part->bd_language) {
202 mailimap_body_fld_lang_print(body_ext_1part->bd_language);
203
204 if (body_ext_1part->bd_extension_list)
205 mailimap_body_extension_list_print(body_ext_1part->bd_extension_list);
206 }
207 }
208
209 unindent();
210 print_indent();
211 printf("}\n");
212}
213
214static void mailimap_body_type_text_print(struct mailimap_body_type_text *
215 body_type_text)
216{
217 print_indent();
218 printf("body-type-text {\n");
219 indent();
220
221 print_indent();
222 printf("media-text { %s }\n", body_type_text->bd_media_text);
223 mailimap_body_fields_print(body_type_text->bd_fields);
224 print_indent();
225 printf("lines { %i }\n", body_type_text->bd_lines);
226
227 unindent();
228 print_indent();
229 printf("}\n");
230}
231
232static void mailimap_body_type_msg_print(struct mailimap_body_type_msg *
233 body_type_msg)
234{
235 print_indent();
236 printf("body-type-msg {\n");
237 indent();
238
239 mailimap_body_fields_print(body_type_msg->bd_fields);
240 mailimap_envelope_print(body_type_msg->bd_envelope);
241 mailimap_body_print(body_type_msg->bd_body);
242
243 print_indent();
244 printf("lines { %i }\n", body_type_msg->bd_lines);
245
246 unindent();
247 print_indent();
248 printf("}\n");
249}
250
251
252static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * fld_enc)
253{
254 print_indent();
255 printf("body-fld-enc { ");
256
257 switch (fld_enc->enc_type) {
258 case MAILIMAP_BODY_FLD_ENC_7BIT:
259 print_indent();
260 printf("7bit");
261 break;
262 case MAILIMAP_BODY_FLD_ENC_8BIT:
263 printf("8bit");
264 break;
265 case MAILIMAP_BODY_FLD_ENC_BINARY:
266 printf("binary");
267 break;
268 case MAILIMAP_BODY_FLD_ENC_BASE64:
269 printf("base64");
270 break;
271 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
272 printf("quoted-printable");
273 break;
274 case MAILIMAP_BODY_FLD_ENC_OTHER:
275 printf("%s", fld_enc->enc_value);
276 break;
277 }
278
279 printf("}\n");
280}
281
282static void mailimap_body_fields_print(struct mailimap_body_fields *
283 body_fields)
284{
285 print_indent();
286 printf("body-fields {\n");
287 indent();
288
289 mailimap_body_fld_param_print(body_fields->bd_parameter);
290
291 print_indent();
292 printf("body-fld-id { %s }\n", body_fields->bd_id);
293 printf("body-fld-desc { %s }\n", body_fields->bd_description);
294 mailimap_body_fld_enc_print(body_fields->bd_encoding);
295 printf("body-fld-octets { %i }\n", body_fields->bd_size);
296
297 unindent();
298 print_indent();
299 printf("}\n");
300}
301
302static void mailimap_media_basic_print(struct mailimap_media_basic *
303 media_basic)
304{
305 print_indent();
306 printf("media-basic {");
307
308 switch (media_basic->med_type) {
309 case MAILIMAP_MEDIA_BASIC_APPLICATION:
310 printf("application");
311 break;
312 case MAILIMAP_MEDIA_BASIC_AUDIO:
313 printf("audio");
314 break;
315 case MAILIMAP_MEDIA_BASIC_IMAGE:
316 printf("image");
317 break;
318 case MAILIMAP_MEDIA_BASIC_MESSAGE:
319 printf("message");
320 break;
321 case MAILIMAP_MEDIA_BASIC_VIDEO:
322 printf("video");
323 break;
324 case MAILIMAP_MEDIA_BASIC_OTHER:
325 printf("%s", media_basic->med_basic_type);
326 break;
327 }
328 printf(" / %s }\n", media_basic->med_subtype);
329}
330
331static void mailimap_body_type_basic_print(struct mailimap_body_type_basic *
332 body_type_basic)
333{
334 print_indent();
335 printf("body-type-basic {\n");
336 indent();
337
338 mailimap_media_basic_print(body_type_basic->bd_media_basic);
339 mailimap_body_fields_print(body_type_basic->bd_fields);
340
341 unindent();
342 print_indent();
343 printf("}\n");
344}
345
346static void mailimap_body_type_1part_print(struct mailimap_body_type_1part *
347 body_type_1part)
348{
349 print_indent();
350 printf("body-type-1part {\n");
351 indent();
352
353 switch (body_type_1part->bd_type) {
354 case MAILIMAP_BODY_TYPE_1PART_BASIC:
355 mailimap_body_type_basic_print(body_type_1part->bd_data.bd_type_basic);
356 break;
357
358 case MAILIMAP_BODY_TYPE_1PART_MSG:
359 mailimap_body_type_msg_print(body_type_1part->bd_data.bd_type_msg);
360 break;
361
362 case MAILIMAP_BODY_TYPE_1PART_TEXT:
363 mailimap_body_type_text_print(body_type_1part->bd_data.bd_type_text);
364 break;
365 }
366
367 if (body_type_1part->bd_ext_1part != NULL)
368 mailimap_body_ext_1part_print(body_type_1part->bd_ext_1part);
369
370 unindent();
371 print_indent();
372 printf("\n");
373}
374
375static void mailimap_body_ext_mpart(struct mailimap_body_ext_mpart * ext_mpart)
376{
377 print_indent();
378 printf("body-ext-mpart {\n");
379 indent();
380
381 mailimap_body_fld_param_print(ext_mpart->bd_parameter);
382 if (ext_mpart->bd_disposition) {
383 mailimap_body_fld_dsp_print(ext_mpart->bd_disposition);
384 if (ext_mpart->bd_language) {
385 mailimap_body_fld_lang_print(ext_mpart->bd_language);
386
387 if (ext_mpart->bd_extension_list)
388 mailimap_body_extension_list_print(ext_mpart->bd_extension_list);
389 }
390 }
391
392 unindent();
393 print_indent();
394 printf("\n");
395}
396
397static void mailimap_body_type_mpart_print(struct mailimap_body_type_mpart *
398 mpart)
399{
400 clistiter * cur;
401
402 print_indent();
403 printf("body-type-mpart {\n");
404 indent();
405
406 for(cur = clist_begin(mpart->bd_list) ; cur != NULL ;
407 cur = clist_next(cur)) {
408 struct mailimap_body * body;
409
410 body = clist_content(cur);
411
412 mailimap_body_print(body);
413 }
414
415 printf("media-subtype { %s }\n", mpart->bd_media_subtype);
416
417 if (mpart->bd_ext_mpart)
418 mailimap_body_ext_mpart(mpart->bd_ext_mpart);
419
420 unindent();
421 print_indent();
422 printf("}\n");
423}
424
425
426static void mailimap_body_print(struct mailimap_body * body)
427{
428 print_indent();
429 printf("body {\n");
430 indent();
431
432 switch (body->bd_type) {
433 case MAILIMAP_BODY_1PART:
434 mailimap_body_type_1part_print(body->bd_data.bd_body_1part);
435 break;
436 case MAILIMAP_BODY_MPART:
437 mailimap_body_type_mpart_print(body->bd_data.bd_body_mpart);
438 break;
439 }
440
441 unindent();
442 print_indent();
443 printf("}\n");
444}
445
446static void mailimap_date_time_print(struct mailimap_date_time * date_time)
447{
448 print_indent();
449 printf("date-time { %i/%i/%i - %i:%i:%i %i }\n",
450 date_time->dt_day, date_time->dt_month, date_time->dt_year,
451 date_time->dt_hour, date_time->dt_min, date_time->dt_month,
452 date_time->dt_zone);
453}
454
455static void mailimap_address_print(struct mailimap_address * address)
456{
457 print_indent();
458 printf("address { name: %s, addr: %s, mailbox: %s, host: %s) }\n",
459 address->ad_personal_name, address->ad_source_route,
460 address->ad_mailbox_name, address->ad_host_name);
461}
462
463static void mailimap_envelope_address_list_print(clist * address)
464{
465 clistiter * cur;
466
467 print_indent();
468 printf("envelope-address-list {\n");
469 indent();
470
471 for(cur = clist_begin(address) ; cur != NULL ;
472 cur = clist_next(cur)) {
473 struct mailimap_address * addr;
474
475 addr = clist_content(cur);
476
477 mailimap_address_print(addr);
478 }
479
480 unindent();
481 print_indent();
482 printf("}\n");
483}
484
485static void mailimap_envelope_print(struct mailimap_envelope * env)
486{
487 print_indent();
488 printf("envelope {\n");
489 indent();
490
491 print_indent();
492 printf("date { %s }\n", env->env_date);
493
494 print_indent();
495 printf("subject { %s }\n", env->env_subject);
496
497 print_indent();
498 printf("from {\n");
499 indent();
500 mailimap_envelope_address_list_print(env->env_from->frm_list);
501 unindent();
502 print_indent();
503 printf("}\n");
504
505 print_indent();
506 printf("sender {\n");
507 indent();
508 mailimap_envelope_address_list_print(env->env_sender->snd_list);
509 unindent();
510 print_indent();
511 printf("}\n");
512
513 print_indent();
514 printf("reply-to {\n");
515 indent();
516 mailimap_envelope_address_list_print(env->env_reply_to->rt_list);
517 unindent();
518 print_indent();
519 printf("}\n");
520
521 print_indent();
522 printf("to {\n");
523 indent();
524 mailimap_envelope_address_list_print(env->env_to->to_list);
525 unindent();
526 print_indent();
527 printf("}\n");
528
529 print_indent();
530 printf("cc {\n");
531 indent();
532 mailimap_envelope_address_list_print(env->env_cc->cc_list);
533 unindent();
534 print_indent();
535 printf("}\n");
536
537 print_indent();
538 printf("bcc {\n");
539 indent();
540 mailimap_envelope_address_list_print(env->env_bcc->bcc_list);
541 unindent();
542 print_indent();
543 printf("}\n");
544
545 printf("in-reply-to { %s }\n", env->env_in_reply_to);
546 printf("message-id { %s }\n", env->env_message_id);
547
548 unindent();
549 print_indent();
550 printf("}\n");
551}
552
553static void mailimap_header_list_print(struct mailimap_header_list *
554 header_list)
555{
556 clistiter * cur;
557
558 print_indent();
559 printf("header-list { ");
560 for(cur = clist_begin(header_list->hdr_list) ; cur != NULL ;
561 cur = clist_next(cur))
562 printf("%s ", (char *) clist_content(cur));
563 printf("}\n");
564}
565
566static void mailimap_section_msgtext_print(struct mailimap_section_msgtext *
567 section_msgtext)
568{
569 print_indent();
570 printf("section-msgtext {\n");
571 indent();
572
573 switch(section_msgtext->sec_type) {
574 case MAILIMAP_SECTION_MSGTEXT_HEADER:
575 print_indent();
576 printf("header\n");
577 break;
578
579 case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS:
580 print_indent();
581 printf("header fields {");
582 indent();
583 mailimap_header_list_print(section_msgtext->sec_header_list);
584 unindent();
585 print_indent();
586 printf("}\n");
587 break;
588
589 case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT:
590 print_indent();
591 printf("header fields not {");
592 indent();
593 mailimap_header_list_print(section_msgtext->sec_header_list);
594 unindent();
595 print_indent();
596 printf("}\n");
597 break;
598
599 case MAILIMAP_SECTION_MSGTEXT_TEXT:
600 print_indent();
601 printf("text\n");
602 break;
603 }
604
605 unindent();
606 print_indent();
607 printf("}\n");
608}
609
610static void mailimap_section_part_print(struct mailimap_section_part *
611 section_part)
612{
613 clistiter * cur;
614
615 print_indent();
616 printf("section-part { ");
617
618 for(cur = clist_begin(section_part->sec_id) ;
619 cur != NULL ; cur = clist_next(cur)) {
620 printf("%i", * ((uint32_t *) clist_content(cur)));
621 if (clist_next(cur) != NULL)
622 printf(".");
623 }
624 printf(" }\n");
625}
626
627static void mailimap_section_text_print(struct mailimap_section_text *
628 section_text)
629{
630 print_indent();
631 printf("section-text {\n");
632 indent();
633
634 switch (section_text->sec_type) {
635 case MAILIMAP_SECTION_TEXT_MIME:
636 print_indent();
637 printf("MIME");
638 break;
639 case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT:
640 mailimap_section_msgtext_print(section_text->sec_msgtext);
641 break;
642 }
643
644 unindent();
645 print_indent();
646 printf("}\n");
647}
648
649static void mailimap_section_spec_print(struct mailimap_section_spec *
650 section_spec)
651{
652 print_indent();
653 printf("section-spec {");
654 indent();
655
656 switch(section_spec->sec_type) {
657 case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT:
658 mailimap_section_msgtext_print(section_spec->sec_data.sec_msgtext);
659 break;
660 case MAILIMAP_SECTION_SPEC_SECTION_PART:
661 mailimap_section_part_print(section_spec->sec_data.sec_part);
662 if (section_spec->sec_text != NULL)
663 mailimap_section_text_print(section_spec->sec_text);
664 break;
665 }
666
667 unindent();
668 print_indent();
669 printf("}\n");
670}
671
672static void mailimap_section_print(struct mailimap_section * section)
673{
674 print_indent();
675 printf("section {\n");
676 indent();
677
678 if (section != NULL)
679 if (section->sec_spec != NULL)
680 mailimap_section_spec_print(section->sec_spec);
681
682 unindent();
683 print_indent();
684 printf("}\n");
685}
686
687static void mailimap_msg_att_body_section_print(struct
688 mailimap_msg_att_body_section *
689 msg_att_body_section)
690{
691 print_indent();
692 printf("msg-att-body-section {\n");
693 indent();
694
695 mailimap_section_print(msg_att_body_section->sec_section);
696 printf("origin-octet: %i\n", msg_att_body_section->sec_origin_octet);
697 printf("body-part: %s\n", msg_att_body_section->sec_body_part);
698
699 unindent();
700 print_indent();
701 printf("}\n");
702}
703
704
705static void mailimap_msg_att_static_print(struct mailimap_msg_att_static *
706 msg_att_static)
707{
708 print_indent();
709 printf("msg-att-static {\n");
710 indent();
711
712 switch (msg_att_static->att_type) {
713
714 case MAILIMAP_MSG_ATT_ENVELOPE:
715 print_indent();
716 printf("envelope {\n");
717 indent();
718 print_indent();
719 mailimap_envelope_print(msg_att_static->att_data.att_env);
720 unindent();
721 print_indent();
722 printf("}\n");
723 break;
724
725 case MAILIMAP_MSG_ATT_INTERNALDATE:
726 print_indent();
727 printf("internaldate {\n");
728 indent();
729 print_indent();
730 mailimap_date_time_print(msg_att_static->att_data.att_internal_date);
731 unindent();
732 print_indent();
733 printf("}\n");
734 break;
735
736 case MAILIMAP_MSG_ATT_RFC822:
737 print_indent();
738 printf("rfc822 {\n");
739 printf("%s\n", msg_att_static->att_data.att_rfc822.att_content);
740 print_indent();
741 printf("}\n");
742 break;
743
744 case MAILIMAP_MSG_ATT_RFC822_HEADER:
745 print_indent();
746 printf("rfc822-header {\n");
747 printf("%s\n", msg_att_static->att_data.att_rfc822_header.att_content);
748 print_indent();
749 printf("}\n");
750 break;
751
752 case MAILIMAP_MSG_ATT_RFC822_TEXT:
753 print_indent();
754 printf("rfc822-text {\n");
755 printf("%s\n", msg_att_static->att_data.att_rfc822_text.att_content);
756 print_indent();
757 printf("}\n");
758 break;
759
760 case MAILIMAP_MSG_ATT_RFC822_SIZE:
761 print_indent();
762 printf("rfc822-size { %i }\n", msg_att_static->att_data.att_rfc822_size);
763 break;
764
765 case MAILIMAP_MSG_ATT_BODY:
766 print_indent();
767 printf("body {\n");
768 indent();
769 print_indent();
770 mailimap_body_print(msg_att_static->att_data.att_body);
771 unindent();
772 print_indent();
773 printf("}\n");
774 break;
775
776 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
777 print_indent();
778 printf("bodystructure {\n");
779 indent();
780 print_indent();
781 mailimap_body_print(msg_att_static->att_data.att_bodystructure);
782 unindent();
783 print_indent();
784 printf("}\n");
785 break;
786
787 case MAILIMAP_MSG_ATT_BODY_SECTION:
788 print_indent();
789 printf("body-section {\n");
790 indent();
791 print_indent();
792 mailimap_msg_att_body_section_print(msg_att_static->att_data.att_body_section);
793 unindent();
794 print_indent();
795 printf("}\n");
796 break;
797
798 case MAILIMAP_MSG_ATT_UID:
799 printf("uid { %i }\n", msg_att_static->att_data.att_uid);
800 break;
801 }
802
803 unindent();
804 print_indent();
805 printf("}\n");
806}
807
808static void mailimap_flag_print(struct mailimap_flag * flag);
809
810static void mailimap_flag_fetch_print(struct mailimap_flag_fetch * flag)
811{
812 print_indent();
813 printf("flag fetch {\n");
814 indent();
815
816 switch (flag->fl_type) {
817 case MAILIMAP_FLAG_FETCH_RECENT:
818 printf("recent\n");
819 break;
820 case MAILIMAP_FLAG_FETCH_OTHER:
821 print_indent();
822 printf("flag {\n");
823 indent();
824 mailimap_flag_print(flag->fl_flag);
825 unindent();
826 print_indent();
827 printf("}\n");
828 break;
829 }
830
831 unindent();
832 print_indent();
833 printf("}\n");
834}
835
836static void mailimap_msg_att_dynamic_print(struct mailimap_msg_att_dynamic *
837 dynamic)
838{
839 clistiter * cur;
840
841 print_indent();
842 printf("msg-att-dynamic {\n");
843 indent();
844
845 for(cur = clist_begin(dynamic->att_list) ; cur != NULL ;
846 cur = clist_next(cur)) {
847 struct mailimap_flag_fetch * flag;
848
849 flag = (struct mailimap_flag_fetch *) clist_content(cur);
850 mailimap_flag_fetch_print(flag);
851 }
852
853 unindent();
854 print_indent();
855 printf("}\n");
856}
857
858static void mailimap_msg_att_item_print(struct mailimap_msg_att_item * item)
859{
860 print_indent();
861 printf("msg-att-item {\n");
862 indent();
863
864 switch (item->att_type) {
865 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
866 mailimap_msg_att_dynamic_print(item->att_data.att_dyn);
867 break;
868 case MAILIMAP_MSG_ATT_ITEM_STATIC:
869 mailimap_msg_att_static_print(item->att_data.att_static);
870 break;
871 }
872
873 unindent();
874 print_indent();
875 printf("}\n");
876}
877
878static void mailimap_msg_att_print(struct mailimap_msg_att * msg_att)
879{
880 clistiter * cur;
881
882 print_indent();
883 printf("msg-att {\n");
884 indent();
885
886 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
887 cur = clist_next(cur)) {
888 struct mailimap_msg_att_item * item;
889
890 item = clist_content(cur);
891
892 mailimap_msg_att_item_print(item);
893 }
894
895 unindent();
896 print_indent();
897 printf("}\n");
898}
899
900static void mailimap_message_data_print(struct mailimap_message_data *
901 msg_data)
902{
903 print_indent();
904 printf("message-data {\n");
905 indent();
906
907 switch (msg_data->mdt_type) {
908 case MAILIMAP_MESSAGE_DATA_EXPUNGE:
909 print_indent();
910 printf("expunged { %i }\n", msg_data->mdt_number);
911 break;
912 case MAILIMAP_MESSAGE_DATA_FETCH:
913 print_indent();
914 printf("message-number { %i }\n", msg_data->mdt_number);
915 mailimap_msg_att_print(msg_data->mdt_msg_att);
916 break;
917 }
918
919 unindent();
920 print_indent();
921 printf("}\n");
922}
923
924static void mailimap_status_att_print(int status_att)
925{
926 print_indent();
927 printf("status-att { ");
928
929 switch(status_att) {
930 case MAILIMAP_STATUS_ATT_MESSAGES:
931 printf("messages");
932 break;
933 case MAILIMAP_STATUS_ATT_RECENT:
934 printf("recent");
935 break;
936 case MAILIMAP_STATUS_ATT_UIDNEXT:
937 printf("uidnext");
938 break;
939 case MAILIMAP_STATUS_ATT_UIDVALIDITY:
940 printf("status att uidvalidity");
941 break;
942 case MAILIMAP_STATUS_ATT_UNSEEN:
943 printf("status att unseen");
944 break;
945 }
946
947 printf(" \n");
948}
949
950static void
951mailimap_status_info_print(struct mailimap_status_info * info)
952{
953 print_indent();
954 printf("status-info {\n");
955 indent();
956
957 mailimap_status_att_print(info->st_att);
958
959 print_indent();
960 printf("value { %i }\n", info->st_value);
961
962 unindent();
963 print_indent();
964 printf("}\n");
965}
966
967static void
968mailimap_mailbox_data_status_print(struct mailimap_mailbox_data_status *
969 mb_data_status)
970{
971 clistiter * cur;
972
973 print_indent();
974 printf("mailbox-data-status {\n");
975 indent();
976
977 print_indent();
978 printf("mailbox { %s }\n", mb_data_status->st_mailbox);
979
980 for(cur = clist_begin(mb_data_status->st_info_list) ;
981 cur != NULL ; cur = clist_next(cur)) {
982 struct mailimap_status_info * info;
983
984 info = clist_content(cur);
985
986 mailimap_status_info_print(info);
987 }
988
989 unindent();
990 print_indent();
991 printf("}\n");
992}
993
994static void mailimap_mbx_list_oflag_print(struct mailimap_mbx_list_oflag *
995 oflag)
996{
997 print_indent();
998 printf("mbx-list-oflag { ");
999
1000 switch (oflag->of_type) {
1001 case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS:
1002 printf("noinferiors");
1003 break;
1004 case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT:
1005 printf("%s", oflag->of_flag_ext);
1006 break;
1007 }
1008
1009 printf(" }\n");
1010}
1011
1012static void mailimap_mbx_list_sflag_print(int sflag)
1013{
1014 print_indent();
1015 printf("mbx-list-sflag { ");
1016
1017 switch (sflag) {
1018 case MAILIMAP_MBX_LIST_SFLAG_MARKED:
1019 printf("marked");
1020 break;
1021 case MAILIMAP_MBX_LIST_SFLAG_NOSELECT:
1022 printf("noselected");
1023 break;
1024 case MAILIMAP_MBX_LIST_SFLAG_UNMARKED:
1025 printf("unmarked");
1026 break;
1027 }
1028
1029 printf(" }\n");
1030}
1031
1032static void mailimap_mbx_list_flags_print(struct mailimap_mbx_list_flags *
1033 mbx_list_flags)
1034{
1035 clistiter * cur;
1036
1037 print_indent();
1038 printf("mbx-list-flags {");
1039 indent();
1040
1041 if (mbx_list_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG)
1042 mailimap_mbx_list_sflag_print(mbx_list_flags->mbf_sflag);
1043
1044 for(cur = clist_begin(mbx_list_flags->mbf_oflags) ; cur != NULL ;
1045 cur = clist_next(cur)) {
1046 struct mailimap_mbx_list_oflag * oflag;
1047
1048 oflag = clist_content(cur);
1049
1050 mailimap_mbx_list_oflag_print(oflag);
1051 }
1052
1053 unindent();
1054 print_indent();
1055 printf("}\n");
1056}
1057
1058static void mailimap_mailbox_list_print(struct mailimap_mailbox_list * mb_list)
1059{
1060 print_indent();
1061 printf("mailbox-list {\n");
1062 indent();
1063
1064 mailimap_mbx_list_flags_print(mb_list->mb_flag);
1065 printf("dir-separator { %c }\n", mb_list->mb_delimiter);
1066 printf("mailbox { %s }\n", mb_list->mb_name);
1067
1068 unindent();
1069 print_indent();
1070 printf("}\n");
1071}
1072
1073static void mailimap_flag_list_print(struct mailimap_flag_list * flag_list)
1074{
1075 clistiter * cur;
1076
1077 print_indent();
1078 printf("flag-list {\n");
1079 indent();
1080
1081 for(cur = clist_begin(flag_list->fl_list) ; cur != NULL ;
1082 cur = clist_next(cur)) {
1083 struct mailimap_flag * flag;
1084
1085 flag = clist_content(cur);
1086
1087 print_indent();
1088 mailimap_flag_print(flag);
1089 printf("\n");
1090 }
1091
1092 unindent();
1093 print_indent();
1094 printf("}\n");
1095}
1096
1097
1098static void mailimap_mailbox_data_print(struct mailimap_mailbox_data * mb_data)
1099{
1100 clistiter * cur;
1101
1102 print_indent();
1103 printf("mailbox-data {\n");
1104 indent();
1105
1106 switch (mb_data->mbd_type) {
1107 case MAILIMAP_MAILBOX_DATA_FLAGS:
1108 print_indent();
1109 printf("flags {\n");
1110 indent();
1111 mailimap_flag_list_print(mb_data->mbd_data.mbd_flags);
1112 unindent();
1113 print_indent();
1114 printf("}\n");
1115 break;
1116
1117 case MAILIMAP_MAILBOX_DATA_LIST:
1118 print_indent();
1119 printf("list {\n");
1120 indent();
1121 mailimap_mailbox_list_print(mb_data->mbd_data.mbd_list);
1122 unindent();
1123 print_indent();
1124 printf("}\n");
1125 break;
1126
1127 case MAILIMAP_MAILBOX_DATA_LSUB:
1128 print_indent();
1129 printf("lsub {\n");
1130 indent();
1131 mailimap_mailbox_list_print(mb_data->mbd_data.mbd_lsub);
1132 unindent();
1133 print_indent();
1134 printf("}\n");
1135 break;
1136
1137 case MAILIMAP_MAILBOX_DATA_SEARCH:
1138 print_indent();
1139 printf("search { ");
1140 for(cur = clist_begin(mb_data->mbd_data.mbd_search) ;
1141 cur != NULL ; cur = clist_next(cur)) {
1142 uint32_t * id;
1143
1144 id = clist_content(cur);
1145 printf("%i ", * id);
1146 }
1147 printf(" }\n");
1148 break;
1149
1150 case MAILIMAP_MAILBOX_DATA_STATUS:
1151 print_indent();
1152 printf("status {\n");
1153 indent();
1154 mailimap_mailbox_data_status_print(mb_data->mbd_data.mbd_status);
1155 unindent();
1156 print_indent();
1157 printf("}\n");
1158 break;
1159
1160 case MAILIMAP_MAILBOX_DATA_EXISTS:
1161 print_indent();
1162 printf("exists { %i }\n", mb_data->mbd_data.mbd_exists);
1163 break;
1164
1165 case MAILIMAP_MAILBOX_DATA_RECENT:
1166 print_indent();
1167 printf("recent { %i }\n", mb_data->mbd_data.mbd_recent);
1168 break;
1169 }
1170
1171 unindent();
1172 print_indent();
1173 printf("}\n");
1174}
1175
1176static void
1177mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code);
1178
1179static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text);
1180
1181static void mailimap_resp_cond_bye_print(struct mailimap_resp_cond_bye *
1182 resp_cond_bye)
1183{
1184 print_indent();
1185 printf("resp-cond-bye {\n");
1186 indent();
1187 mailimap_resp_text_print(resp_cond_bye->rsp_text);
1188 unindent();
1189 print_indent();
1190 printf("}\n");
1191}
1192
1193static void mailimap_resp_cond_state_print(struct mailimap_resp_cond_state *
1194 resp_cond_state)
1195{
1196 print_indent();
1197 printf("resp-cond-state {\n");
1198 indent();
1199
1200 switch(resp_cond_state->rsp_type) {
1201 case MAILIMAP_RESP_COND_STATE_OK:
1202 print_indent();
1203 printf("OK\n");
1204 break;
1205 case MAILIMAP_RESP_COND_STATE_NO:
1206 print_indent();
1207 printf("NO\n");
1208 break;
1209 case MAILIMAP_RESP_COND_STATE_BAD:
1210 print_indent();
1211 printf("BAD\n");
1212 break;
1213 }
1214
1215 mailimap_resp_text_print(resp_cond_state->rsp_text);
1216
1217 unindent();
1218 print_indent();
1219 printf("}\n");
1220}
1221
1222static void mailimap_capability_data_print(struct mailimap_capability_data *
1223 cap_data);
1224
1225static void mailimap_response_data_print(struct mailimap_response_data *
1226 resp_data)
1227{
1228 print_indent();
1229 printf("response-data {\n");
1230 indent();
1231
1232 switch (resp_data->rsp_type) {
1233 case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
1234 mailimap_resp_cond_state_print(resp_data->rsp_data.rsp_cond_state);
1235 break;
1236 case MAILIMAP_RESP_DATA_TYPE_COND_BYE:
1237 mailimap_resp_cond_bye_print(resp_data->rsp_data.rsp_bye);
1238 break;
1239 case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
1240 mailimap_mailbox_data_print(resp_data->rsp_data.rsp_mailbox_data);
1241 break;
1242 case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
1243 mailimap_message_data_print(resp_data->rsp_data.rsp_message_data);
1244 break;
1245 case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
1246 mailimap_capability_data_print(resp_data->rsp_data.rsp_capability_data);
1247 break;
1248 }
1249
1250 unindent();
1251 print_indent();
1252 printf("}\n");
1253}
1254
1255static void mailimap_flag_print(struct mailimap_flag * flag)
1256{
1257 printf("flag { ");
1258
1259 switch (flag->fl_type) {
1260 case MAILIMAP_FLAG_ANSWERED:
1261 printf("answered");
1262 break;
1263
1264 case MAILIMAP_FLAG_FLAGGED:
1265 printf("flagged");
1266 break;
1267
1268 case MAILIMAP_FLAG_DELETED:
1269 printf("deleted");
1270 break;
1271
1272 case MAILIMAP_FLAG_SEEN:
1273 printf("seen");
1274 break;
1275
1276 case MAILIMAP_FLAG_DRAFT:
1277 printf("flag draft");
1278 break;
1279
1280 case MAILIMAP_FLAG_KEYWORD:
1281 printf("keyword { %s }", flag->fl_data.fl_keyword);
1282 break;
1283
1284 case MAILIMAP_FLAG_EXTENSION:
1285 printf("extention { %s }", flag->fl_data.fl_extension);
1286 break;
1287 }
1288
1289 printf(" }");
1290}
1291
1292static void mailimap_flag_perm_print(struct mailimap_flag_perm * flag_perm)
1293{
1294 print_indent();
1295 printf("flag-perm { ");
1296
1297 switch (flag_perm->fl_type) {
1298 case MAILIMAP_FLAG_PERM_FLAG:
1299 mailimap_flag_print(flag_perm->fl_flag);
1300 break;
1301
1302 case MAILIMAP_FLAG_PERM_ALL:
1303 printf("all");
1304 break;
1305 }
1306
1307 printf(" }\n");
1308}
1309
1310static void mailimap_capability_print(struct mailimap_capability * cap)
1311{
1312 print_indent();
1313 printf("capability { ");
1314
1315 switch (cap->cap_type) {
1316 case MAILIMAP_CAPABILITY_AUTH_TYPE:
1317 printf("auth { %s }", cap->cap_data.cap_auth_type);
1318 break;
1319 case MAILIMAP_CAPABILITY_NAME:
1320 printf("atom { %s }", cap->cap_data.cap_name);
1321 break;
1322 }
1323
1324 printf(" }\n");
1325}
1326
1327static void mailimap_capability_data_print(struct mailimap_capability_data *
1328 cap_data)
1329{
1330 clistiter * cur;
1331
1332 print_indent();
1333 printf("capability-data {\n");
1334 indent();
1335
1336 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ;
1337 cur = clist_next(cur)) {
1338 struct mailimap_capability * cap;
1339
1340 cap = clist_content(cur);
1341
1342 mailimap_capability_print(cap);
1343 }
1344
1345 unindent();
1346 print_indent();
1347 printf("}\n");
1348}
1349
1350static void
1351mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code)
1352{
1353 clistiter * cur;
1354
1355 print_indent();
1356 printf("resp-text-code {\n");
1357 indent();
1358
1359 switch (text_code->rc_type) {
1360 case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
1361 print_indent();
1362 printf("badcharset { ");
1363 for(cur = clist_begin(text_code->rc_data.rc_badcharset) ; cur != NULL ;
1364 cur = clist_next(cur))
1365 printf("%s ", (char *) clist_content(cur));
1366 printf("}\n");
1367 break;
1368
1369 case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
1370 print_indent();
1371 printf("capability {\n");
1372 indent();
1373 mailimap_capability_data_print(text_code->rc_data.rc_cap_data);
1374 unindent();
1375 print_indent();
1376 printf("}\n");
1377 break;
1378
1379 case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
1380 print_indent();
1381 printf("permanent-flags {\n");
1382 indent();
1383 cur = clist_begin(text_code->rc_data.rc_perm_flags);
1384 while (cur != NULL) {
1385 mailimap_flag_perm_print(clist_content(cur));
1386 cur = clist_next(cur);
1387 }
1388 unindent();
1389 print_indent();
1390 printf("}\n");
1391 break;
1392
1393 case MAILIMAP_RESP_TEXT_CODE_READ_ONLY:
1394 print_indent();
1395 printf("readonly\n");
1396 break;
1397
1398 case MAILIMAP_RESP_TEXT_CODE_READ_WRITE:
1399 print_indent();
1400 printf("readwrite\n");
1401 break;
1402
1403 case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE:
1404 print_indent();
1405 printf("trycreate\n");
1406 break;
1407
1408 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
1409 print_indent();
1410 printf("uidnext { %i }\n", text_code->rc_data.rc_uidnext);
1411 break;
1412
1413 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
1414 print_indent();
1415 printf("uidvalidity { %i }\n", text_code->rc_data.rc_uidvalidity);
1416 break;
1417
1418 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
1419 print_indent();
1420 printf("unseen { %i }\n", text_code->rc_data.rc_first_unseen);
1421 break;
1422
1423 case MAILIMAP_RESP_TEXT_CODE_OTHER:
1424 print_indent();
1425 printf("other { %s = %s }\n",
1426 text_code->rc_data.rc_atom.atom_name,
1427 text_code->rc_data.rc_atom.atom_value);
1428 break;
1429 }
1430
1431 unindent();
1432 print_indent();
1433 printf("}\n");
1434}
1435
1436static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text)
1437{
1438 print_indent();
1439 printf("resp-text {\n");
1440 indent();
1441
1442 if (resp_text->rsp_code)
1443 mailimap_resp_text_code_print(resp_text->rsp_code);
1444 print_indent();
1445 printf("text { %s }\n", resp_text->rsp_text);
1446
1447 unindent();
1448 print_indent();
1449 printf("}\n");
1450}
1451
1452static void mailimap_continue_req_print(struct mailimap_continue_req *
1453 cont_req)
1454{
1455 print_indent();
1456 printf("continue-req {\n");
1457 indent();
1458
1459 switch (cont_req->cr_type) {
1460 case MAILIMAP_CONTINUE_REQ_TEXT:
1461 print_indent();
1462 printf("resp-text {\n");
1463 indent();
1464 mailimap_resp_text_print(cont_req->cr_data.cr_text);
1465 unindent();
1466 print_indent();
1467 printf("}\n");
1468 break;
1469 case MAILIMAP_CONTINUE_REQ_BASE64:
1470 printf("base64 { %s }\n", cont_req->cr_data.cr_base64);
1471 break;
1472 }
1473
1474 unindent();
1475 print_indent();
1476 printf("}\n");
1477}
1478
1479static void mailimap_cont_req_or_resp_data_print(struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data)
1480{
1481 print_indent();
1482 printf("cont-req-or-resp-data {\n");
1483 indent();
1484
1485 switch (cont_req_or_resp_data->rsp_type) {
1486 case MAILIMAP_RESP_CONT_REQ:
1487 mailimap_continue_req_print(cont_req_or_resp_data->rsp_data.rsp_cont_req);
1488 break;
1489 case MAILIMAP_RESP_RESP_DATA:
1490 mailimap_response_data_print(cont_req_or_resp_data->rsp_data.rsp_resp_data);
1491 break;
1492 }
1493
1494 unindent();
1495 print_indent();
1496 printf("}\n");
1497}
1498
1499static void mailimap_response_tagged_print(struct mailimap_response_tagged *
1500 tagged)
1501{
1502 print_indent();
1503 printf("response-tagged {\n");
1504 indent();
1505
1506 print_indent();
1507 printf("tag { %s }\n", tagged->rsp_tag);
1508 mailimap_resp_cond_state_print(tagged->rsp_cond_state);
1509
1510 unindent();
1511 print_indent();
1512 printf("}\n");
1513}
1514
1515static void mailimap_response_fatal_print(struct mailimap_response_fatal *
1516 fatal)
1517{
1518 print_indent();
1519 printf("response-fatal {\n");
1520 indent();
1521
1522 mailimap_resp_cond_bye_print(fatal->rsp_bye);
1523
1524 unindent();
1525 print_indent();
1526 printf("}\n");
1527}
1528
1529static void mailimap_response_done_print(struct mailimap_response_done *
1530 resp_done)
1531{
1532 print_indent();
1533 printf("response-done {\n");
1534 indent();
1535
1536 switch (resp_done->rsp_type) {
1537 case MAILIMAP_RESP_DONE_TYPE_TAGGED:
1538 mailimap_response_tagged_print(resp_done->rsp_data.rsp_tagged);
1539 break;
1540 case MAILIMAP_RESP_DONE_TYPE_FATAL:
1541 mailimap_response_fatal_print(resp_done->rsp_data.rsp_fatal);
1542 break;
1543 }
1544
1545 unindent();
1546 print_indent();
1547 printf("}\n");
1548}
1549
1550void mailimap_response_print(struct mailimap_response * resp)
1551{
1552 clistiter * cur;
1553
1554 print_indent();
1555 printf("response {\n");
1556 indent();
1557
1558 for(cur = clist_begin(resp->rsp_cont_req_or_resp_data_list) ; cur != NULL ;
1559 cur = clist_next(cur)) {
1560 struct mailimap_cont_req_or_resp_data * resp;
1561
1562 resp = clist_content(cur);
1563
1564 mailimap_cont_req_or_resp_data_print(resp);
1565 }
1566
1567 mailimap_response_done_print(resp->rsp_resp_done);
1568
1569 unindent();
1570 print_indent();
1571 printf("}\n");
1572}
1573
1574static void mailimap_resp_cond_auth_print(struct mailimap_resp_cond_auth *
1575 cond_auth)
1576{
1577 print_indent();
1578 printf("resp-cond-auth {\n");
1579 indent();
1580
1581 switch (cond_auth->rsp_type) {
1582 case MAILIMAP_RESP_COND_AUTH_OK:
1583 print_indent();
1584 printf("OK\n");
1585 case MAILIMAP_RESP_COND_AUTH_PREAUTH:
1586 print_indent();
1587 printf("PREAUTH\n");
1588 }
1589 mailimap_resp_text_print(cond_auth->rsp_text);
1590
1591 unindent();
1592 print_indent();
1593 printf("}\n");
1594}
1595
1596void mailimap_greeting_print(struct mailimap_greeting * greeting)
1597{
1598 print_indent();
1599 printf("greeting {\n");
1600 indent();
1601
1602 switch(greeting->gr_type) {
1603 case MAILIMAP_GREETING_RESP_COND_AUTH:
1604 mailimap_resp_cond_auth_print(greeting->gr_data.gr_auth);
1605 break;
1606 case MAILIMAP_GREETING_RESP_COND_BYE:
1607 mailimap_resp_cond_bye_print(greeting->gr_data.gr_bye);
1608 break;
1609 }
1610
1611 unindent();
1612 print_indent();
1613 printf("}\n");
1614}
1615#endif
diff --git a/libetpan/src/low-level/imap/mailimap_print.h b/libetpan/src/low-level/imap/mailimap_print.h
new file mode 100644
index 0000000..b617cca
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_print.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_PRINT_H
37
38#define MAILIMAP_PRINT_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailimap_types.h"
45
46void mailimap_response_print(struct mailimap_response * resp);
47
48void mailimap_greeting_print(struct mailimap_greeting * greeting);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/low-level/imap/mailimap_sender.c b/libetpan/src/low-level/imap/mailimap_sender.c
new file mode 100644
index 0000000..caf86e5
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_sender.c
@@ -0,0 +1,2742 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream.h"
37#include "mailimap_keywords.h"
38#include "mailimap_sender.h"
39#include "clist.h"
40#include "mail.h"
41#include <string.h>
42
43#include <stdio.h>
44#include <ctype.h>
45
46/*
47 TODO :
48 implement progression for literal
49*/
50
51/* ************************************************************************* */
52/* ************************************************************************* */
53/* ************************************************************************* */
54/* ************************************************************************* */
55/* ************************************************************************* */
56/* ************************************************************************* */
57
58
59
60
61static int mailimap_atom_send(mailstream * fd, const char * atom);
62
63static int mailimap_auth_type_send(mailstream * fd, const char * auth_type);
64
65static int mailimap_base64_send(mailstream * fd, const char * base64);
66
67
68static int mailimap_date_send(mailstream * fd,
69 struct mailimap_date * date);
70
71static int mailimap_date_day_send(mailstream * fd, int day);
72
73static int mailimap_date_month_send(mailstream * fd, int month);
74
75
76/*
77static gboolean mailimap_date_text_send(mailstream * fd,
78 struct mailimap_date_text * date_text);
79*/
80
81
82static int mailimap_date_year_send(mailstream *fd, int year);
83
84static int
85mailimap_date_time_send(mailstream * fd,
86 struct mailimap_date_time * date_time);
87
88static int mailimap_digit_send(mailstream * fd, int digit);
89
90
91
92static int
93mailimap_fetch_type_send(mailstream * fd,
94 struct mailimap_fetch_type * fetch_type);
95
96
97static int mailimap_fetch_att_send(mailstream * fd,
98 struct mailimap_fetch_att * fetch_att);
99
100
101static int mailimap_flag_send(mailstream * fd,
102 struct mailimap_flag * flag);
103
104
105static int mailimap_flag_extension_send(mailstream * fd,
106 const char * flag_extension);
107
108
109static int mailimap_flag_keyword_send(mailstream * fd,
110 const char * flag_keyword);
111
112
113static int mailimap_flag_list_send(mailstream * fd,
114 struct mailimap_flag_list * flag_list);
115
116
117
118static int mailimap_header_fld_name_send(mailstream * fd, const char * header);
119
120
121static int
122mailimap_header_list_send(mailstream * fd,
123 struct mailimap_header_list * header_list);
124
125static int
126mailimap_list_mailbox_send(mailstream * fd, const char * pattern);
127
128
129static int mailimap_mailbox_send(mailstream * fd, const char * mb);
130
131static int mailimap_number_send(mailstream * fd, uint32_t number);
132
133static int mailimap_password_send(mailstream * fd, const char * pass);
134
135static int mailimap_quoted_char_send(mailstream * fd, char ch);
136
137static int mailimap_quoted_send(mailstream * fd, const char * quoted);
138
139
140static int mailimap_search_key_send(mailstream * fd,
141 struct mailimap_search_key * key);
142
143static int
144mailimap_section_send(mailstream * fd,
145 struct mailimap_section * section);
146
147static int
148mailimap_section_msgtext_send(mailstream * fd,
149 struct mailimap_section_msgtext *
150 section_msgtext);
151
152
153static int
154mailimap_section_part_send(mailstream * fd,
155 struct mailimap_section_part * section);
156
157
158static int
159mailimap_section_spec_send(mailstream * fd,
160 struct mailimap_section_spec * section_spec);
161
162
163static int
164mailimap_section_text_send(mailstream * fd,
165 struct mailimap_section_text * section_text);
166
167
168static int
169mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num);
170
171
172static int mailimap_set_item_send(mailstream * fd,
173 struct mailimap_set_item * item);
174
175
176static int mailimap_set_send(mailstream * fd,
177 struct mailimap_set * set);
178
179
180
181static int mailimap_status_att_send(mailstream * fd, int * status_att);
182
183
184
185static int
186mailimap_store_att_flags_send(mailstream * fd,
187 struct mailimap_store_att_flags * store_flags);
188
189
190static int mailimap_userid_send(mailstream * fd, const char * user);
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205/* ************************************************************************* */
206/* ************************************************************************* */
207/* ************************************************************************* */
208/* ************************************************************************* */
209/* ************************************************************************* */
210/* ************************************************************************* */
211
212
213
214
215
216static inline int mailimap_sized_token_send(mailstream * fd, const char * atom,
217 size_t len)
218{
219 if (mailstream_send_data_crlf(fd, atom, len, 0, NULL) == -1)
220 return MAILIMAP_ERROR_STREAM;
221
222 return MAILIMAP_NO_ERROR;
223}
224
225static int mailimap_token_send(mailstream * fd, const char * atom)
226{
227 return mailimap_sized_token_send(fd, atom, strlen(atom));
228}
229
230static int mailimap_char_send(mailstream * fd, char ch)
231{
232 if (mailstream_write(fd, &ch, 1) == -1)
233 return MAILIMAP_ERROR_STREAM;
234
235 return MAILIMAP_NO_ERROR;
236}
237
238typedef int mailimap_struct_sender(mailstream * fd, void * data);
239
240static int
241mailimap_struct_list_send(mailstream * fd, clist * list,
242 char symbol,
243 mailimap_struct_sender * sender)
244{
245 clistiter * cur;
246 void * elt;
247 int r;
248
249 cur = clist_begin(list);
250
251 if (cur == NULL)
252 return MAILIMAP_NO_ERROR;
253
254 elt = clist_content(cur);
255 r = (* sender)(fd, elt);
256 if (r != MAILIMAP_NO_ERROR)
257 return r;
258 cur = clist_next(cur);
259
260 while (cur != NULL) {
261 r = mailimap_char_send(fd, symbol);
262 if (r != MAILIMAP_NO_ERROR)
263 return r;
264 elt = clist_content(cur);
265 r = (* sender)(fd, elt);
266 if (r != MAILIMAP_NO_ERROR)
267 return r;
268 cur = clist_next(cur);
269 }
270
271 return MAILIMAP_NO_ERROR;
272}
273
274
275static int
276mailimap_struct_spaced_list_send(mailstream * fd, clist * list,
277 mailimap_struct_sender * sender)
278{
279 return mailimap_struct_list_send(fd, list, ' ', sender);
280}
281
282int mailimap_space_send(mailstream * fd)
283{
284 return mailimap_char_send(fd, ' ');
285}
286
287int mailimap_crlf_send(mailstream * fd)
288{
289 int r;
290
291 r = mailimap_char_send(fd, '\r');
292 if (r != MAILIMAP_NO_ERROR)
293 return r;
294 r = mailimap_char_send(fd, '\n');
295 if (r != MAILIMAP_NO_ERROR)
296 return r;
297
298 return MAILIMAP_NO_ERROR;
299}
300
301static int mailimap_oparenth_send(mailstream * fd)
302{
303 return mailimap_char_send(fd, '(');
304}
305
306static int mailimap_cparenth_send(mailstream * fd)
307{
308 return mailimap_char_send(fd, ')');
309}
310
311static int mailimap_dquote_send(mailstream * fd)
312{
313 return mailimap_char_send(fd, '"');
314}
315
316/*
317 address = "(" addr-name SP addr-adl SP addr-mailbox SP
318 addr-host ")"
319
320 addr-adl = nstring
321 ; Holds route from [RFC-822] route-addr if
322 ; non-NIL
323
324 addr-host = nstring
325 ; NIL indicates [RFC-822] group syntax.
326 ; Otherwise, holds [RFC-822] domain name
327
328 addr-mailbox = nstring
329 ; NIL indicates end of [RFC-822] group; if
330 ; non-NIL and addr-host is NIL, holds
331 ; [RFC-822] group name.
332 ; Otherwise, holds [RFC-822] local-part
333 ; after removing [RFC-822] quoting
334
335 addr-name = nstring
336 ; If non-NIL, holds phrase from [RFC-822]
337 ; mailbox after removing [RFC-822] quoting
338*/
339
340/*
341=> append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
342 literal
343*/
344
345int mailimap_append_send(mailstream * fd,
346 const char * mailbox,
347 struct mailimap_flag_list * flag_list,
348 struct mailimap_date_time * date_time,
349 size_t literal_size)
350{
351 int r;
352
353 r = mailimap_token_send(fd, "APPEND");
354 if (r != MAILIMAP_NO_ERROR)
355 return r;
356 r = mailimap_space_send(fd);
357 if (r != MAILIMAP_NO_ERROR)
358 return r;
359 r = mailimap_mailbox_send(fd, mailbox);
360 if (r != MAILIMAP_NO_ERROR)
361 return r;
362 if (flag_list != NULL) {
363 r = mailimap_space_send(fd);
364 if (r != MAILIMAP_NO_ERROR)
365 return r;
366 r = mailimap_flag_list_send(fd, flag_list);
367 if (r != MAILIMAP_NO_ERROR)
368 return r;
369 }
370 if (date_time != NULL) {
371 r = mailimap_space_send(fd);
372 if (r != MAILIMAP_NO_ERROR)
373 return r;
374 r = mailimap_date_time_send(fd, date_time);
375 if (r != MAILIMAP_NO_ERROR)
376 return r;
377 }
378
379 r = mailimap_space_send(fd);
380 if (r != MAILIMAP_NO_ERROR)
381 return r;
382 r = mailimap_literal_count_send(fd, literal_size);
383 if (r != MAILIMAP_NO_ERROR)
384 return r;
385
386 return MAILIMAP_NO_ERROR;
387}
388
389/*
390 astring = 1*ASTRING-CHAR / string
391
392=> ASTRING-CHAR = ATOM-CHAR / resp-specials
393*/
394
395static int is_atom(const char * str)
396{
397 if (* str == '\0')
398 return 0;
399
400 while (* str != '\0') {
401 unsigned char uch = (unsigned char) * str;
402
403 if (!isalnum(uch))
404 return 0;
405
406 str ++;
407 }
408
409 return 1;
410}
411
412static int mailimap_astring_send(mailstream * fd, const char * astring)
413{
414 /*
415 workaround for buggy Courier-IMAP that does not accept
416 quoted-strings for fields name but prefer atoms.
417 */
418 if (is_atom(astring))
419 return mailimap_atom_send(fd, astring);
420 else
421 return mailimap_quoted_send(fd, astring);
422}
423
424/*
425=> atom = 1*ATOM-CHAR
426*/
427
428static int mailimap_atom_send(mailstream * fd, const char * atom)
429{
430 return mailimap_token_send(fd, atom);
431}
432
433/*
434=> ATOM-CHAR = <any CHAR except atom-specials>
435*/
436
437/*
438=> atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
439 quoted-specials / resp-specials
440*/
441
442/*
443=> authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
444*/
445
446int mailimap_authenticate_send(mailstream * fd,
447 const char * auth_type)
448{
449 int r;
450
451 r = mailimap_token_send(fd, "AUTHENTICATE");
452 if (r != MAILIMAP_NO_ERROR)
453 return r;
454 r = mailimap_space_send(fd);
455 if (r != MAILIMAP_NO_ERROR)
456 return r;
457 r = mailimap_auth_type_send(fd, auth_type);
458 if (r != MAILIMAP_NO_ERROR)
459 return r;
460
461 return MAILIMAP_NO_ERROR;
462}
463
464int mailimap_authenticate_resp_send(mailstream * fd,
465 const char * base64)
466{
467 int r;
468
469 r = mailimap_base64_send(fd, base64);
470 if (r != MAILIMAP_NO_ERROR)
471 return r;
472
473 return MAILIMAP_NO_ERROR;
474}
475
476/*
477=> auth-type = atom
478 ; Defined by [SASL]
479*/
480
481static int mailimap_auth_type_send(mailstream * fd, const char * auth_type)
482{
483 return mailimap_atom_send(fd, auth_type);
484}
485
486
487/*
488=> base64 = *(4base64-char) [base64-terminal]
489*/
490
491static int mailimap_base64_send(mailstream * fd, const char * base64)
492{
493 return mailimap_token_send(fd, base64);
494}
495
496/*
497=> base64-char = ALPHA / DIGIT / "+" / "/"
498 ; Case-sensitive
499
500 base64-terminal = (2base64-char "==") / (3base64-char "=")
501
502 body = "(" (body-type-1part / body-type-mpart) ")"
503
504 body-extension = nstring / number /
505 "(" body-extension *(SP body-extension) ")"
506 ; Future expansion. Client implementations
507 ; MUST accept body-extension fields. Server
508 ; implementations MUST NOT generate
509 ; body-extension fields except as defined by
510 ; future standard or standards-track
511 ; revisions of this specification.
512
513 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
514 *(SP body-extension)]]
515 ; MUST NOT be returned on non-extensible
516 ; "BODY" fetch
517
518 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
519 *(SP body-extension)]]
520 ; MUST NOT be returned on non-extensible
521 ; "BODY" fetch
522
523 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
524 body-fld-enc SP body-fld-octets
525
526 body-fld-desc = nstring
527
528 body-fld-dsp = "(" string SP body-fld-param ")" / nil
529
530 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
531 "QUOTED-PRINTABLE") DQUOTE) / string
532
533 body-fld-id = nstring
534
535 body-fld-lang = nstring / "(" string *(SP string) ")"
536
537 body-fld-lines = number
538
539 body-fld-md5 = nstring
540
541 body-fld-octets = number
542
543 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
544
545 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
546 [SP body-ext-1part]
547
548 body-type-basic = media-basic SP body-fields
549 ; MESSAGE subtype MUST NOT be "RFC822"
550
551 body-type-mpart = 1*body SP media-subtype
552 [SP body-ext-mpart]
553
554 body-type-msg = media-message SP body-fields SP envelope
555 SP body SP body-fld-lines
556
557 body-type-text = media-text SP body-fields SP body-fld-lines
558
559 capability = ("AUTH=" auth-type) / atom
560 ; New capabilities MUST begin with "X" or be
561 ; registered with IANA as standard or
562 ; standards-track
563
564 capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
565 *(SP capability)
566 ; IMAP4rev1 servers which offer RFC 1730
567 ; compatibility MUST list "IMAP4" as the first
568 ; capability.
569
570 CHAR8 = %x01-ff
571 ; any OCTET except NUL, %x00
572*/
573
574/*
575=> command = tag SP (command-any / command-auth / command-nonauth /
576 command-select) CRLF
577 ; Modal based on state
578*/
579
580/*
581=> command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
582 ; Valid in all states
583*/
584
585int mailimap_capability_send(mailstream * fd)
586{
587 int r;
588
589 r = mailimap_token_send(fd, "CAPABILITY");
590 if (r != MAILIMAP_NO_ERROR)
591 return r;
592
593 return MAILIMAP_NO_ERROR;
594}
595
596int mailimap_logout_send(mailstream * fd)
597{
598 int r;
599
600 r = mailimap_token_send(fd, "LOGOUT");
601 if (r != MAILIMAP_NO_ERROR)
602 return r;
603
604 return MAILIMAP_NO_ERROR;
605}
606
607int mailimap_noop_send(mailstream * fd)
608{
609 int r;
610
611 r = mailimap_token_send(fd, "NOOP");
612 if (r != MAILIMAP_NO_ERROR)
613 return r;
614
615 return MAILIMAP_NO_ERROR;
616}
617
618/*
619=> command-auth = append / create / delete / examine / list / lsub /
620 rename / select / status / subscribe / unsubscribe
621 ; Valid only in Authenticated or Selected state
622*/
623
624/*
625=> command-nonauth = login / authenticate
626 ; Valid only when in Not Authenticated state
627*/
628
629/*
630=> command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
631 uid / search
632 ; Valid only when in Selected state
633*/
634
635int mailimap_check_send(mailstream * fd)
636{
637 int r;
638
639 r = mailimap_token_send(fd, "CHECK");
640 if (r != MAILIMAP_NO_ERROR)
641 return r;
642
643 return MAILIMAP_NO_ERROR;
644}
645
646int mailimap_close_send(mailstream * fd)
647{
648 int r;
649
650 r = mailimap_token_send(fd, "CLOSE");
651 if (r != MAILIMAP_NO_ERROR)
652 return r;
653
654 return MAILIMAP_NO_ERROR;
655}
656
657int mailimap_expunge_send(mailstream * fd)
658{
659 int r;
660
661 r = mailimap_token_send(fd, "EXPUNGE");
662 if (r != MAILIMAP_NO_ERROR)
663 return r;
664
665 return MAILIMAP_NO_ERROR;
666}
667
668/*
669 continue-req = "+" SP (resp-text / base64) CRLF
670*/
671
672/*
673=> copy = "COPY" SP set SP mailbox
674*/
675
676int mailimap_copy_send(mailstream * fd,
677 struct mailimap_set * set,
678 const char * mb)
679{
680 int r;
681
682 r = mailimap_token_send(fd, "COPY");
683 if (r != MAILIMAP_NO_ERROR)
684 return r;
685
686 r = mailimap_space_send(fd);
687 if (r != MAILIMAP_NO_ERROR)
688 return r;
689
690 r = mailimap_set_send(fd, set);
691 if (r != MAILIMAP_NO_ERROR)
692 return r;
693
694 r = mailimap_space_send(fd);
695 if (r != MAILIMAP_NO_ERROR)
696 return r;
697
698 r = mailimap_mailbox_send(fd, mb);
699 if (r != MAILIMAP_NO_ERROR)
700 return r;
701
702 return MAILIMAP_NO_ERROR;
703}
704
705int mailimap_uid_copy_send(mailstream * fd,
706 struct mailimap_set * set,
707 const char * mb)
708{
709 int r;
710
711 r = mailimap_token_send(fd, "UID");
712 if (r != MAILIMAP_NO_ERROR)
713 return r;
714
715 r = mailimap_space_send(fd);
716 if (r != MAILIMAP_NO_ERROR)
717 return r;
718
719 return mailimap_copy_send(fd, set, mb);
720}
721
722/*
723=> create = "CREATE" SP mailbox
724 ; Use of INBOX gives a NO error
725*/
726
727int mailimap_create_send(mailstream * fd,
728 const char * mb)
729{
730 int r;
731
732 r = mailimap_token_send(fd, "CREATE");
733 if (r != MAILIMAP_NO_ERROR)
734 return r;
735
736 r = mailimap_space_send(fd);
737 if (r != MAILIMAP_NO_ERROR)
738 return r;
739
740 r = mailimap_mailbox_send(fd, mb);
741 if (r != MAILIMAP_NO_ERROR)
742 return r;
743
744 return MAILIMAP_NO_ERROR;
745}
746
747/*
748=> date = date-text / DQUOTE date-text DQUOTE
749*/
750
751static int mailimap_date_send(mailstream * fd,
752 struct mailimap_date * date)
753{
754 int r;
755
756 r = mailimap_date_day_send(fd, date->dt_day);
757 if (r != MAILIMAP_NO_ERROR)
758 return r;
759
760 r = mailimap_char_send(fd, '-');
761 if (r != MAILIMAP_NO_ERROR)
762 return r;
763
764 r = mailimap_date_month_send(fd, date->dt_month);
765 if (r != MAILIMAP_NO_ERROR)
766 return r;
767
768 r = mailimap_char_send(fd, '-');
769 if (r != MAILIMAP_NO_ERROR)
770 return r;
771
772 r = mailimap_date_year_send(fd, date->dt_year);
773 if (r != MAILIMAP_NO_ERROR)
774 return r;
775
776 return MAILIMAP_NO_ERROR;
777}
778
779/*
780=> date-day = 1*2DIGIT
781 ; Day of month
782*/
783
784static int mailimap_date_day_send(mailstream * fd, int day)
785{
786 return mailimap_number_send(fd, day);
787}
788
789/*
790=> date-day-fixed = (SP DIGIT) / 2DIGIT
791 ; Fixed-format version of date-day
792*/
793
794static int mailimap_date_day_fixed_send(mailstream * fd, int day)
795{
796 int r;
797
798 if (day < 10) {
799 r = mailimap_space_send(fd);
800 if (r != MAILIMAP_NO_ERROR)
801 return r;
802
803 r = mailimap_number_send(fd, day);
804 if (r != MAILIMAP_NO_ERROR)
805 return r;
806
807 return MAILIMAP_NO_ERROR;
808 }
809 else
810 return mailimap_number_send(fd, day);
811}
812
813/*
814=> date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
815 "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
816*/
817
818static int mailimap_date_month_send(mailstream * fd, int month)
819{
820 const char * name;
821 int r;
822
823 name = mailimap_month_get_token_str(month);
824
825 if (name == NULL)
826 return MAILIMAP_ERROR_INVAL;
827
828 r = mailimap_token_send(fd, name);
829 if (r != MAILIMAP_NO_ERROR)
830 return r;
831
832 return MAILIMAP_NO_ERROR;
833}
834
835/*
836=> date-text = date-day "-" date-month "-" date-year
837*/
838
839/*
840static gboolean mailimap_date_text_send(mailstream * fd,
841 struct mailimap_date_text * date_text)
842{
843 if (!mailimap_date_day_send(fd, date_text->day))
844 return FALSE;
845 if (!mailimap_char_send(fd, '-'))
846 return FALSE;
847 if (!mailimap_date_month_send(fd, date_text->month))
848 return FALSE;
849 if (!mailimap_char_send(fd, '-'))
850 return FALSE;
851 if (!mailimap_date_year_send(fd, date_text->year))
852 return FALSE;
853
854 return TRUE;
855}
856*/
857
858/*
859=> date-year = 4DIGIT
860*/
861
862static int mailimap_fixed_digit_send(mailstream * fd,
863 int num, int count)
864{
865 int r;
866
867 r = mailimap_fixed_digit_send(fd, num / 10, count);
868 if (r != MAILIMAP_NO_ERROR)
869 return r;
870
871 r = mailimap_digit_send(fd, num % 10);
872 if (r != MAILIMAP_NO_ERROR)
873 return r;
874
875 return MAILIMAP_NO_ERROR;
876}
877
878static int mailimap_date_year_send(mailstream *fd, int year)
879{
880 int r;
881
882 r = mailimap_fixed_digit_send(fd, year, 4);
883 if (r != MAILIMAP_NO_ERROR)
884 return r;
885
886 return MAILIMAP_NO_ERROR;
887}
888
889/*
890=> date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
891 SP time SP zone DQUOTE
892*/
893
894static int
895mailimap_date_time_send(mailstream * fd,
896 struct mailimap_date_time * date_time)
897{
898 int r;
899
900 r = mailimap_date_day_fixed_send(fd, date_time->dt_day);
901 if (r != MAILIMAP_NO_ERROR)
902 return r;
903
904 r = mailimap_char_send(fd, '-');
905 if (r != MAILIMAP_NO_ERROR)
906 return r;
907
908 r = mailimap_date_month_send(fd, date_time->dt_month);
909 if (r != MAILIMAP_NO_ERROR)
910 return r;
911
912 r = mailimap_char_send(fd, '-');
913 if (r != MAILIMAP_NO_ERROR)
914 return r;
915
916 r = mailimap_date_year_send(fd, date_time->dt_month);
917 if (r != MAILIMAP_NO_ERROR)
918 return r;
919
920 r = mailimap_space_send(fd);
921 if (r != MAILIMAP_NO_ERROR)
922 return r;
923
924 r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2);
925 if (r != MAILIMAP_NO_ERROR)
926 return r;
927
928 r = mailimap_char_send(fd, ':');
929 if (r != MAILIMAP_NO_ERROR)
930 return r;
931
932 r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2);
933 if (r != MAILIMAP_NO_ERROR)
934 return r;
935
936 r = mailimap_char_send(fd, ':');
937 if (r != MAILIMAP_NO_ERROR)
938 return r;
939
940 r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2);
941 if (r != MAILIMAP_NO_ERROR)
942 return r;
943
944 return MAILIMAP_NO_ERROR;
945}
946
947/*
948=> delete = "DELETE" SP mailbox
949 ; Use of INBOX gives a NO error
950*/
951
952int mailimap_delete_send(mailstream * fd, const char * mb)
953{
954 int r;
955
956 r = mailimap_token_send(fd, "DELETE");
957 if (r != MAILIMAP_NO_ERROR)
958 return r;
959
960 r = mailimap_space_send(fd);
961 if (r != MAILIMAP_NO_ERROR)
962 return r;
963
964 r = mailimap_mailbox_send(fd, mb);
965 if (r != MAILIMAP_NO_ERROR)
966 return r;
967
968 return MAILIMAP_NO_ERROR;
969}
970
971/*
972
973digit
974
975digit-nz = %x31-39
976 ; 1-9
977*/
978
979static int mailimap_digit_send(mailstream * fd, int digit)
980{
981 return mailimap_char_send(fd, digit + '0');
982}
983
984
985/*
986 envelope = "(" env-date SP env-subject SP env-from SP env-sender SP
987 env-reply-to SP env-to SP env-cc SP env-bcc SP
988 env-in-reply-to SP env-message-id ")"
989
990 env-bcc = "(" 1*address ")" / nil
991
992 env-cc = "(" 1*address ")" / nil
993
994 env-date = nstring
995
996 env-from = "(" 1*address ")" / nil
997
998 env-in-reply-to = nstring
999
1000 env-message-id = nstring
1001
1002 env-reply-to = "(" 1*address ")" / nil
1003
1004 env-sender = "(" 1*address ")" / nil
1005
1006 env-subject = nstring
1007
1008 env-to = "(" 1*address ")" / nil
1009*/
1010
1011/*
1012=> examine = "EXAMINE" SP mailbox
1013*/
1014
1015int mailimap_examine_send(mailstream * fd, const char * mb)
1016{
1017 int r;
1018
1019 r = mailimap_token_send(fd, "EXAMINE");
1020 if (r != MAILIMAP_NO_ERROR)
1021 return r;
1022
1023 r = mailimap_space_send(fd);
1024 if (r != MAILIMAP_NO_ERROR)
1025 return r;
1026
1027 r = mailimap_mailbox_send(fd, mb);
1028 if (r != MAILIMAP_NO_ERROR)
1029 return r;
1030
1031 return MAILIMAP_NO_ERROR;
1032}
1033
1034/*
1035=> fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att /
1036 "(" fetch-att *(SP fetch-att) ")")
1037*/
1038
1039static int
1040mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list);
1041
1042static int
1043mailimap_fetch_type_send(mailstream * fd,
1044 struct mailimap_fetch_type * fetch_type)
1045{
1046 switch (fetch_type->ft_type) {
1047 case MAILIMAP_FETCH_TYPE_ALL:
1048 return mailimap_token_send(fd, "ALL");
1049 case MAILIMAP_FETCH_TYPE_FULL:
1050 return mailimap_token_send(fd, "FULL");
1051 case MAILIMAP_FETCH_TYPE_FAST:
1052 return mailimap_token_send(fd, "FAST");
1053 case MAILIMAP_FETCH_TYPE_FETCH_ATT:
1054 return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att);
1055 case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST:
1056 return mailimap_fetch_att_list_send(fd,
1057 fetch_type->ft_data.ft_fetch_att_list);
1058 default:
1059 /* should not happen */
1060 return MAILIMAP_ERROR_INVAL;
1061 }
1062}
1063
1064int mailimap_fetch_send(mailstream * fd,
1065 struct mailimap_set * set,
1066 struct mailimap_fetch_type * fetch_type)
1067{
1068 int r;
1069
1070 r = mailimap_token_send(fd, "FETCH");
1071 if (r != MAILIMAP_NO_ERROR)
1072 return r;
1073
1074 r = mailimap_space_send(fd);
1075 if (r != MAILIMAP_NO_ERROR)
1076 return r;
1077
1078 r = mailimap_set_send(fd, set);
1079 if (r != MAILIMAP_NO_ERROR)
1080 return r;
1081
1082 r = mailimap_space_send(fd);
1083 if (r != MAILIMAP_NO_ERROR)
1084 return r;
1085
1086 r = mailimap_fetch_type_send(fd, fetch_type);
1087 if (r != MAILIMAP_NO_ERROR)
1088 return r;
1089
1090 return MAILIMAP_NO_ERROR;
1091}
1092
1093int
1094mailimap_uid_fetch_send(mailstream * fd,
1095 struct mailimap_set * set,
1096 struct mailimap_fetch_type * fetch_type)
1097{
1098 int r;
1099
1100 r = mailimap_token_send(fd, "UID");
1101 if (r != MAILIMAP_NO_ERROR)
1102 return r;
1103
1104 r = mailimap_space_send(fd);
1105 if (r != MAILIMAP_NO_ERROR)
1106 return r;
1107
1108 return mailimap_fetch_send(fd, set, fetch_type);
1109}
1110
1111/* currently porting */
1112
1113static int
1114mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list)
1115{
1116 int r;
1117
1118 r = mailimap_oparenth_send(fd);
1119 if (r != MAILIMAP_NO_ERROR)
1120 return r;
1121
1122 r = mailimap_struct_spaced_list_send(fd, fetch_att_list,
1123 (mailimap_struct_sender *)
1124 mailimap_fetch_att_send);
1125 if (r != MAILIMAP_NO_ERROR)
1126 return r;
1127
1128 r = mailimap_cparenth_send(fd);
1129 if (r != MAILIMAP_NO_ERROR)
1130 return r;
1131
1132 return MAILIMAP_NO_ERROR;
1133}
1134
1135/*
1136=> fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
1137 "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
1138 "BODY" ["STRUCTURE"] / "UID" /
1139 "BODY" [".PEEK"] section ["<" number "." nz-number ">"]
1140*/
1141
1142static int mailimap_fetch_att_send(mailstream * fd,
1143 struct mailimap_fetch_att * fetch_att)
1144{
1145 int r;
1146
1147 switch(fetch_att->att_type) {
1148 case MAILIMAP_FETCH_ATT_ENVELOPE:
1149 return mailimap_token_send(fd, "ENVELOPE");
1150
1151 case MAILIMAP_FETCH_ATT_FLAGS:
1152 return mailimap_token_send(fd, "FLAGS");
1153
1154 case MAILIMAP_FETCH_ATT_INTERNALDATE:
1155 return mailimap_token_send(fd, "INTERNALDATE");
1156
1157 case MAILIMAP_FETCH_ATT_RFC822:
1158 return mailimap_token_send(fd, "RFC822");
1159
1160 case MAILIMAP_FETCH_ATT_RFC822_HEADER:
1161 return mailimap_token_send(fd, "RFC822.HEADER");
1162
1163 case MAILIMAP_FETCH_ATT_RFC822_SIZE:
1164 return mailimap_token_send(fd, "RFC822.SIZE");
1165
1166 case MAILIMAP_FETCH_ATT_RFC822_TEXT:
1167 return mailimap_token_send(fd, "RFC822.TEXT");
1168
1169 case MAILIMAP_FETCH_ATT_BODY:
1170 return mailimap_token_send(fd, "BODY");
1171
1172 case MAILIMAP_FETCH_ATT_BODYSTRUCTURE:
1173 return mailimap_token_send(fd, "BODYSTRUCTURE");
1174
1175 case MAILIMAP_FETCH_ATT_UID:
1176 return mailimap_token_send(fd, "UID");
1177
1178 case MAILIMAP_FETCH_ATT_BODY_SECTION:
1179
1180 r = mailimap_token_send(fd, "BODY");
1181 if (r != MAILIMAP_NO_ERROR)
1182 return r;
1183 r = mailimap_section_send(fd, fetch_att->att_section);
1184 if (r != MAILIMAP_NO_ERROR)
1185 return r;
1186 if (fetch_att->att_size != 0) {
1187 r = mailimap_char_send(fd, '<');
1188 if (r != MAILIMAP_NO_ERROR)
1189 return r;
1190 r = mailimap_number_send(fd, fetch_att->att_offset);
1191 if (r != MAILIMAP_NO_ERROR)
1192 return r;
1193 r = mailimap_char_send(fd, '.');
1194 if (r != MAILIMAP_NO_ERROR)
1195 return r;
1196 r = mailimap_number_send(fd, fetch_att->att_size);
1197 if (r != MAILIMAP_NO_ERROR)
1198 return r;
1199 r = mailimap_char_send(fd, '>');
1200 if (r != MAILIMAP_NO_ERROR)
1201 return r;
1202 }
1203
1204 return MAILIMAP_NO_ERROR;
1205
1206 case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION:
1207 r = mailimap_token_send(fd, "BODY.PEEK");
1208 if (r != MAILIMAP_NO_ERROR)
1209 return r;
1210 r = mailimap_section_send(fd, fetch_att->att_section);
1211 if (r != MAILIMAP_NO_ERROR)
1212 return r;
1213 if (fetch_att->att_size != 0) {
1214 r = mailimap_char_send(fd, '<');
1215 if (r != MAILIMAP_NO_ERROR)
1216 return r;
1217 r = mailimap_number_send(fd, fetch_att->att_offset);
1218 if (r != MAILIMAP_NO_ERROR)
1219 return r;
1220 r = mailimap_char_send(fd, '.');
1221 if (r != MAILIMAP_NO_ERROR)
1222 return r;
1223 r = mailimap_number_send(fd, fetch_att->att_size);
1224 if (r != MAILIMAP_NO_ERROR)
1225 return r;
1226 r = mailimap_char_send(fd, '>');
1227 if (r != MAILIMAP_NO_ERROR)
1228 return r;
1229 }
1230 return MAILIMAP_NO_ERROR;
1231
1232 default:
1233 /* should not happen */
1234 return MAILIMAP_ERROR_INVAL;
1235 }
1236}
1237
1238/*
1239=> flag = "\Answered" / "\Flagged" / "\Deleted" /
1240 "\Seen" / "\Draft" / flag-keyword / flag-extension
1241 ; Does not include "\Recent"
1242*/
1243
1244/*
1245enum {
1246 FLAG_ANSWERED,
1247 FLAG_FLAGGED,
1248 FLAG_DELETED,
1249 FLAG_SEEN,
1250 FLAG_DRAFT,
1251 FLAG_KEYWORD,
1252 FLAG_EXTENSION
1253};
1254
1255struct mailimap_flag {
1256 gint type;
1257 gchar * flag_keyword;
1258 gchar * flag_extension;
1259};
1260*/
1261
1262static int mailimap_flag_send(mailstream * fd,
1263 struct mailimap_flag * flag)
1264{
1265 switch(flag->fl_type) {
1266 case MAILIMAP_FLAG_ANSWERED:
1267 return mailimap_token_send(fd, "\\Answered");
1268 case MAILIMAP_FLAG_FLAGGED:
1269 return mailimap_token_send(fd, "\\Flagged");
1270 case MAILIMAP_FLAG_DELETED:
1271 return mailimap_token_send(fd, "\\Deleted");
1272 case MAILIMAP_FLAG_SEEN:
1273 return mailimap_token_send(fd, "\\Seen");
1274 case MAILIMAP_FLAG_DRAFT:
1275 return mailimap_token_send(fd, "\\Draft");
1276 case MAILIMAP_FLAG_KEYWORD:
1277 return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword);
1278 case MAILIMAP_FLAG_EXTENSION:
1279 return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension);
1280 default:
1281 /* should not happen */
1282 return MAILIMAP_ERROR_INVAL;
1283 }
1284}
1285
1286
1287/*
1288=> flag-extension = "\" atom
1289 ; Future expansion. Client implementations
1290 ; MUST accept flag-extension flags. Server
1291 ; implementations MUST NOT generate
1292 ; flag-extension flags except as defined by
1293 ; future standard or standards-track
1294 ; revisions of this specification.
1295*/
1296
1297static int mailimap_flag_extension_send(mailstream * fd,
1298 const char * flag_extension)
1299{
1300 int r;
1301
1302 r = mailimap_char_send(fd, '\\');
1303 if (r != MAILIMAP_NO_ERROR)
1304 return r;
1305
1306 r = mailimap_atom_send(fd, flag_extension);
1307 if (r != MAILIMAP_NO_ERROR)
1308 return r;
1309
1310 return MAILIMAP_NO_ERROR;
1311}
1312
1313/*
1314 flag-fetch = flag / "\Recent"
1315*/
1316
1317/*
1318=> flag-keyword = atom
1319*/
1320
1321static int mailimap_flag_keyword_send(mailstream * fd,
1322 const char * flag_keyword)
1323{
1324 return mailimap_token_send(fd, flag_keyword);
1325}
1326
1327/*
1328=> flag-list = "(" [flag *(SP flag)] ")"
1329*/
1330
1331static int mailimap_flag_list_send(mailstream * fd,
1332 struct mailimap_flag_list * flag_list)
1333{
1334 int r;
1335
1336 r = mailimap_oparenth_send(fd);
1337 if (r != MAILIMAP_NO_ERROR)
1338 return r;
1339
1340 if (flag_list->fl_list != NULL) {
1341 r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list,
1342 (mailimap_struct_sender *) mailimap_flag_send);
1343 if (r != MAILIMAP_NO_ERROR)
1344 return r;
1345 }
1346
1347 r = mailimap_cparenth_send(fd);
1348 if (r != MAILIMAP_NO_ERROR)
1349 return r;
1350
1351 return MAILIMAP_NO_ERROR;
1352}
1353
1354/*
1355 flag-perm = flag / "\*"
1356
1357 greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
1358*/
1359
1360/*
1361=> header-fld-name = astring
1362*/
1363
1364static int mailimap_header_fld_name_send(mailstream * fd, const char * header)
1365{
1366 return mailimap_astring_send(fd, header);
1367}
1368
1369/*
1370=> header-list = "(" header-fld-name *(SP header-fld-name) ")"
1371*/
1372
1373static int
1374mailimap_header_list_send(mailstream * fd,
1375 struct mailimap_header_list * header_list)
1376{
1377 int r;
1378
1379 r = mailimap_oparenth_send(fd);
1380 if (r != MAILIMAP_NO_ERROR)
1381 return r;
1382
1383 r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list,
1384 (mailimap_struct_sender *) mailimap_header_fld_name_send);
1385 if (r != MAILIMAP_NO_ERROR)
1386 return r;
1387
1388 r = mailimap_cparenth_send(fd);
1389 if (r != MAILIMAP_NO_ERROR)
1390 return r;
1391
1392 return MAILIMAP_NO_ERROR;
1393}
1394
1395/*
1396=> list = "LIST" SP mailbox SP list-mailbox
1397*/
1398
1399int mailimap_list_send(mailstream * fd,
1400 const char * mb,
1401 const char * list_mb)
1402{
1403 int r;
1404
1405 r = mailimap_token_send(fd, "LIST");
1406 if (r != MAILIMAP_NO_ERROR)
1407 return r;
1408
1409 r = mailimap_space_send(fd);
1410 if (r != MAILIMAP_NO_ERROR)
1411 return r;
1412
1413 r = mailimap_mailbox_send(fd, mb);
1414 if (r != MAILIMAP_NO_ERROR)
1415 return r;
1416
1417 r = mailimap_space_send(fd);
1418 if (r != MAILIMAP_NO_ERROR)
1419 return r;
1420
1421 r = mailimap_list_mailbox_send(fd, list_mb);
1422 if (r != MAILIMAP_NO_ERROR)
1423 return r;
1424
1425 return MAILIMAP_NO_ERROR;
1426}
1427
1428/*
1429=> list-mailbox = 1*list-char / string
1430*/
1431
1432static int
1433mailimap_list_mailbox_send(mailstream * fd, const char * pattern)
1434{
1435 return mailimap_quoted_send(fd, pattern);
1436}
1437
1438/*
1439 list-char = ATOM-CHAR / list-wildcards / resp-specials
1440
1441 list-wildcards = "%" / "*"
1442*/
1443
1444/*
1445=> literal = "{" number "}" CRLF *CHAR8
1446 ; Number represents the number of CHAR8s
1447*/
1448
1449int
1450mailimap_literal_send(mailstream * fd, const char * literal,
1451 size_t progr_rate,
1452 progress_function * progr_fun)
1453{
1454 size_t len;
1455 uint32_t literal_len;
1456 int r;
1457
1458 len = strlen(literal);
1459 literal_len = mailstream_get_data_crlf_size(literal, len);
1460
1461 r = mailimap_literal_count_send(fd, literal_len);
1462 if (r != MAILIMAP_NO_ERROR)
1463 return r;
1464 r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun);
1465 if (r != MAILIMAP_NO_ERROR)
1466 return r;
1467
1468 return MAILIMAP_NO_ERROR;
1469}
1470
1471/*
1472 "{" number "}" CRLF
1473*/
1474
1475int
1476mailimap_literal_count_send(mailstream * fd, uint32_t count)
1477{
1478 int r;
1479
1480 r = mailimap_char_send(fd, '{');
1481 if (r != MAILIMAP_NO_ERROR)
1482 return r;
1483
1484 r = mailimap_number_send(fd, count);
1485 if (r != MAILIMAP_NO_ERROR)
1486 return r;
1487
1488 r = mailimap_char_send(fd, '}');
1489 if (r != MAILIMAP_NO_ERROR)
1490 return r;
1491
1492 r = mailimap_crlf_send(fd);
1493 if (r != MAILIMAP_NO_ERROR)
1494 return r;
1495
1496 return MAILIMAP_NO_ERROR;
1497}
1498
1499/*
1500 *CHAR8
1501*/
1502
1503int
1504mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len,
1505 size_t progr_rate,
1506 progress_function * progr_fun)
1507{
1508 int r;
1509
1510 r = mailimap_sized_token_send(fd, literal, len);
1511 if (r != MAILIMAP_NO_ERROR)
1512 return r;
1513
1514 return MAILIMAP_NO_ERROR;
1515}
1516
1517
1518/*
1519=> login = "LOGIN" SP userid SP password
1520*/
1521
1522int mailimap_login_send(mailstream * fd,
1523 const char * userid, const char * password)
1524{
1525 int r;
1526
1527 r = mailimap_token_send(fd, "LOGIN");
1528 if (r != MAILIMAP_NO_ERROR)
1529 return r;
1530
1531 r = mailimap_space_send(fd);
1532 if (r != MAILIMAP_NO_ERROR)
1533 return r;
1534
1535 r = mailimap_userid_send(fd, userid);
1536 if (r != MAILIMAP_NO_ERROR)
1537 return r;
1538
1539 r = mailimap_space_send(fd);
1540 if (r != MAILIMAP_NO_ERROR)
1541 return r;
1542
1543 r = mailimap_password_send(fd, password);
1544 if (r != MAILIMAP_NO_ERROR)
1545 return r;
1546
1547 return MAILIMAP_NO_ERROR;
1548}
1549
1550/*
1551=> lsub = "LSUB" SP mailbox SP list-mailbox
1552*/
1553
1554int mailimap_lsub_send(mailstream * fd,
1555 const char * mb, const char * list_mb)
1556{
1557 int r;
1558
1559 r = mailimap_token_send(fd, "LSUB");
1560 if (r != MAILIMAP_NO_ERROR)
1561 return r;
1562
1563 r = mailimap_space_send(fd);
1564 if (r != MAILIMAP_NO_ERROR)
1565 return r;
1566
1567 r = mailimap_mailbox_send(fd, mb);
1568 if (r != MAILIMAP_NO_ERROR)
1569 return r;
1570
1571 r = mailimap_space_send(fd);
1572 if (r != MAILIMAP_NO_ERROR)
1573 return r;
1574
1575 r = mailimap_list_mailbox_send(fd, list_mb);
1576 if (r != MAILIMAP_NO_ERROR)
1577 return r;
1578
1579 return MAILIMAP_NO_ERROR;
1580}
1581
1582/*
1583 mailbox = "INBOX" / astring
1584 ; INBOX is case-insensitive. All case variants of
1585 ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
1586 ; not as an astring. An astring which consists of
1587 ; the case-insensitive sequence "I" "N" "B" "O" "X"
1588 ; is considered to be INBOX and not an astring.
1589 ; Refer to section 5.1 for further
1590 ; semantic details of mailbox names.
1591*/
1592
1593static int mailimap_mailbox_send(mailstream * fd, const char * mb)
1594{
1595 return mailimap_astring_send(fd, mb);
1596}
1597
1598/*
1599 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
1600 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
1601 "STATUS" SP mailbox SP "("
1602 [status-att SP number *(SP status-att SP number)] ")" /
1603 number SP "EXISTS" / number SP "RECENT"
1604
1605 mailbox-list = "(" [mbx-list-flags] ")" SP
1606 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
1607
1608 mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
1609 *(SP mbx-list-oflag) /
1610 mbx-list-oflag *(SP mbx-list-oflag)
1611
1612 mbx-list-oflag = "\Noinferiors" / flag-extension
1613 ; Other flags; multiple possible per LIST response
1614
1615 mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
1616 ; Selectability flags; only one per LIST response
1617
1618 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
1619 "VIDEO") DQUOTE) / string) SP media-subtype
1620 ; Defined in [MIME-IMT]
1621
1622 media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
1623 ; Defined in [MIME-IMT]
1624
1625 media-subtype = string
1626 ; Defined in [MIME-IMT]
1627
1628 media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
1629 ; Defined in [MIME-IMT]
1630
1631 message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
1632
1633 msg-att = "(" (msg-att-dynamic / msg-att-static)
1634 *(SP (msg-att-dynamic / msg-att-static)) ")"
1635
1636 msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
1637 ; MAY change for a message
1638
1639 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
1640 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
1641 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
1642 "BODY" section ["<" number ">"] SP nstring /
1643 "UID" SP uniqueid
1644 ; MUST NOT change for a message
1645
1646 nil = "NIL"
1647
1648 nstring = string / nil
1649*/
1650
1651/*
1652=> number = 1*DIGIT
1653 ; Unsigned 32-bit integer
1654 ; (0 <= n < 4,294,967,296)
1655*/
1656
1657/*
1658 nz-number = digit-nz *DIGIT
1659 ; Non-zero unsigned 32-bit integer
1660 ; (0 < n < 4,294,967,296)
1661*/
1662
1663static int mailimap_number_send(mailstream * fd, uint32_t number)
1664{
1665 int r;
1666
1667 if (number / 10 != 0) {
1668 r = mailimap_number_send(fd, number / 10);
1669 if (r != MAILIMAP_NO_ERROR)
1670 return r;
1671 }
1672
1673 r = mailimap_digit_send(fd, number % 10);
1674 if (r != MAILIMAP_NO_ERROR)
1675 return r;
1676
1677 return MAILIMAP_NO_ERROR;
1678}
1679
1680/*
1681=> password = astring
1682*/
1683
1684static int mailimap_password_send(mailstream * fd, const char * pass)
1685{
1686 return mailimap_astring_send(fd, pass);
1687}
1688
1689/*
1690=> quoted = DQUOTE *QUOTED-CHAR DQUOTE
1691
1692=> QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
1693 "\" quoted-specials
1694
1695=> quoted-specials = DQUOTE / "\"
1696*/
1697
1698static int is_quoted_specials(char ch)
1699{
1700 return (ch == '\"') || (ch == '\\');
1701}
1702
1703static int mailimap_quoted_char_send(mailstream * fd, char ch)
1704{
1705 int r;
1706
1707 if (is_quoted_specials(ch)) {
1708 r = mailimap_char_send(fd, '\\');
1709 if (r != MAILIMAP_NO_ERROR)
1710 return r;
1711 r = mailimap_char_send(fd, ch);
1712 if (r != MAILIMAP_NO_ERROR)
1713 return r;
1714
1715 return MAILIMAP_NO_ERROR;
1716 }
1717 else
1718 return mailimap_char_send(fd, ch);
1719}
1720
1721static int mailimap_quoted_send(mailstream * fd, const char * quoted)
1722{
1723 const char * pos;
1724 int r;
1725
1726 pos = quoted;
1727
1728 r = mailimap_dquote_send(fd);
1729 if (r != MAILIMAP_NO_ERROR)
1730 return r;
1731
1732 while (* pos != 0) {
1733 r = mailimap_quoted_char_send(fd, * pos);
1734 if (r != MAILIMAP_NO_ERROR)
1735 return r;
1736 pos ++;
1737 }
1738
1739 r = mailimap_dquote_send(fd);
1740 if (r != MAILIMAP_NO_ERROR)
1741 return r;
1742
1743 return MAILIMAP_NO_ERROR;
1744}
1745
1746/*
1747=> rename = "RENAME" SP mailbox SP mailbox
1748 ; Use of INBOX as a destination gives a NO error
1749*/
1750
1751int mailimap_rename_send(mailstream * fd, const char * mb,
1752 const char * new_name)
1753{
1754 int r;
1755
1756 r = mailimap_token_send(fd, "RENAME");
1757 if (r != MAILIMAP_NO_ERROR)
1758 return r;
1759 r = mailimap_space_send(fd);
1760 if (r != MAILIMAP_NO_ERROR)
1761 return r;
1762 r = mailimap_mailbox_send(fd, mb);
1763 if (r != MAILIMAP_NO_ERROR)
1764 return r;
1765 r = mailimap_space_send(fd);
1766 if (r != MAILIMAP_NO_ERROR)
1767 return r;
1768 r = mailimap_mailbox_send(fd, new_name);
1769 if (r != MAILIMAP_NO_ERROR)
1770 return r;
1771
1772 return MAILIMAP_NO_ERROR;
1773}
1774
1775/*
1776 response = *(continue-req / response-data) response-done
1777
1778 response-data = "*" SP (resp-cond-state / resp-cond-bye /
1779 mailbox-data / message-data / capability-data) CRLF
1780
1781 response-done = response-tagged / response-fatal
1782
1783 response-fatal = "*" SP resp-cond-bye CRLF
1784 ; Server closes connection immediately
1785
1786 response-tagged = tag SP resp-cond-state CRLF
1787
1788 resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
1789 ; Authentication condition
1790
1791 resp-cond-bye = "BYE" SP resp-text
1792
1793 resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
1794 ; Status condition
1795
1796 resp-specials = "]"
1797
1798 resp-text = ["[" resp-text-code "]" SP] text
1799
1800 resp-text-code = "ALERT" /
1801 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
1802 capability-data / "PARSE" /
1803 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
1804 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
1805 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
1806 "UNSEEN" SP nz-number /
1807 atom [SP 1*<any TEXT-CHAR except "]">]
1808*/
1809
1810/*
1811=> search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
1812 ; CHARSET argument to MUST be registered with IANA
1813*/
1814
1815int
1816mailimap_search_send(mailstream * fd, const char * charset,
1817 struct mailimap_search_key * key)
1818{
1819 int r;
1820
1821 r = mailimap_token_send(fd, "SEARCH");
1822 if (r != MAILIMAP_NO_ERROR)
1823 return r;
1824
1825 if (charset != NULL) {
1826 r = mailimap_space_send(fd);
1827 if (r != MAILIMAP_NO_ERROR)
1828 return r;
1829
1830 r = mailimap_token_send(fd, "CHARSET");
1831 if (r != MAILIMAP_NO_ERROR)
1832 return r;
1833 r = mailimap_space_send(fd);
1834 if (r != MAILIMAP_NO_ERROR)
1835 return r;
1836 r = mailimap_astring_send(fd, charset);
1837 if (r != MAILIMAP_NO_ERROR)
1838 return r;
1839 }
1840
1841 r = mailimap_space_send(fd);
1842 if (r != MAILIMAP_NO_ERROR)
1843 return r;
1844
1845 r = mailimap_search_key_send(fd, key);
1846 if (r != MAILIMAP_NO_ERROR)
1847 return r;
1848
1849 return MAILIMAP_NO_ERROR;
1850}
1851
1852int
1853mailimap_uid_search_send(mailstream * fd, const char * charset,
1854 struct mailimap_search_key * key)
1855{
1856 int r;
1857
1858 r = mailimap_token_send(fd, "UID");
1859 if (r != MAILIMAP_NO_ERROR)
1860 return r;
1861
1862 r = mailimap_space_send(fd);
1863 if (r != MAILIMAP_NO_ERROR)
1864 return r;
1865
1866 return mailimap_search_send(fd, charset, key);
1867}
1868
1869
1870/*
1871=> search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
1872 "BEFORE" SP date / "BODY" SP astring /
1873 "CC" SP astring / "DELETED" / "FLAGGED" /
1874 "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" /
1875 "OLD" / "ON" SP date / "RECENT" / "SEEN" /
1876 "SINCE" SP date / "SUBJECT" SP astring /
1877 "TEXT" SP astring / "TO" SP astring /
1878 "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
1879 "UNKEYWORD" SP flag-keyword / "UNSEEN" /
1880 ; Above this line were in [IMAP2]
1881 "DRAFT" / "HEADER" SP header-fld-name SP astring /
1882 "LARGER" SP number / "NOT" SP search-key /
1883 "OR" SP search-key SP search-key /
1884 "SENTBEFORE" SP date / "SENTON" SP date /
1885 "SENTSINCE" SP date / "SMALLER" SP number /
1886 "UID" SP set / "UNDRAFT" / set /
1887 "(" search-key *(SP search-key) ")"
1888*/
1889
1890
1891static int mailimap_search_key_send(mailstream * fd,
1892 struct mailimap_search_key * key)
1893{
1894 int r;
1895
1896 switch (key->sk_type) {
1897
1898 case MAILIMAP_SEARCH_KEY_ALL:
1899 return mailimap_token_send(fd, "ALL");
1900
1901 case MAILIMAP_SEARCH_KEY_ANSWERED:
1902 return mailimap_token_send(fd, "ANSWERED");
1903
1904 case MAILIMAP_SEARCH_KEY_BCC:
1905 r = mailimap_token_send(fd, "BCC");
1906 if (r != MAILIMAP_NO_ERROR)
1907 return r;
1908 r = mailimap_space_send(fd);
1909 if (r != MAILIMAP_NO_ERROR)
1910 return r;
1911 r = mailimap_astring_send(fd, key->sk_data.sk_bcc);
1912 if (r != MAILIMAP_NO_ERROR)
1913 return r;
1914 return MAILIMAP_NO_ERROR;
1915
1916 case MAILIMAP_SEARCH_KEY_BEFORE:
1917 r = mailimap_token_send(fd, "BEFORE");
1918 if (r != MAILIMAP_NO_ERROR)
1919 return r;
1920 r = mailimap_space_send(fd);
1921 if (r != MAILIMAP_NO_ERROR)
1922 return r;
1923 r = mailimap_date_send(fd, key->sk_data.sk_before);
1924 if (r != MAILIMAP_NO_ERROR)
1925 return r;
1926 return MAILIMAP_NO_ERROR;
1927
1928 case MAILIMAP_SEARCH_KEY_BODY:
1929 r = mailimap_token_send(fd, "BODY");
1930 if (r != MAILIMAP_NO_ERROR)
1931 return r;
1932 r = mailimap_space_send(fd);
1933 if (r != MAILIMAP_NO_ERROR)
1934 return r;
1935 r = mailimap_astring_send(fd, key->sk_data.sk_body);
1936 if (r != MAILIMAP_NO_ERROR)
1937 return r;
1938 return MAILIMAP_NO_ERROR;
1939
1940 case MAILIMAP_SEARCH_KEY_CC:
1941 r = mailimap_token_send(fd, "CC");
1942 if (r != MAILIMAP_NO_ERROR)
1943 return r;
1944 r = mailimap_space_send(fd);
1945 if (r != MAILIMAP_NO_ERROR)
1946 return r;
1947 r = mailimap_astring_send(fd, key->sk_data.sk_cc);
1948 if (r != MAILIMAP_NO_ERROR)
1949 return r;
1950 return MAILIMAP_NO_ERROR;
1951
1952 case MAILIMAP_SEARCH_KEY_DELETED:
1953 return mailimap_token_send(fd, "DELETED");
1954
1955 case MAILIMAP_SEARCH_KEY_FLAGGED:
1956 return mailimap_token_send(fd, "FLAGGED");
1957
1958 case MAILIMAP_SEARCH_KEY_FROM:
1959 r = mailimap_token_send(fd, "FROM");
1960 if (r != MAILIMAP_NO_ERROR)
1961 return r;
1962 r = mailimap_space_send(fd);
1963 if (r != MAILIMAP_NO_ERROR)
1964 return r;
1965 r = mailimap_astring_send(fd, key->sk_data.sk_from);
1966 if (r != MAILIMAP_NO_ERROR)
1967 return r;
1968 return MAILIMAP_NO_ERROR;
1969
1970 case MAILIMAP_SEARCH_KEY_KEYWORD:
1971 r = mailimap_token_send(fd, "KEYWORD");
1972 if (r != MAILIMAP_NO_ERROR)
1973 return r;
1974 r = mailimap_space_send(fd);
1975 if (r != MAILIMAP_NO_ERROR)
1976 return r;
1977 r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword);
1978 if (r != MAILIMAP_NO_ERROR)
1979 return r;
1980 return MAILIMAP_NO_ERROR;
1981
1982 case MAILIMAP_SEARCH_KEY_NEW:
1983 return mailimap_token_send(fd, "NEW");
1984
1985 case MAILIMAP_SEARCH_KEY_OLD:
1986 return mailimap_token_send(fd, "OLD");
1987
1988 case MAILIMAP_SEARCH_KEY_ON:
1989 r = mailimap_token_send(fd, "ON");
1990 if (r != MAILIMAP_NO_ERROR)
1991 return r;
1992 r = mailimap_space_send(fd);
1993 if (r != MAILIMAP_NO_ERROR)
1994 return r;
1995 r = mailimap_date_send(fd, key->sk_data.sk_on);
1996 if (r != MAILIMAP_NO_ERROR)
1997 return r;
1998 return MAILIMAP_NO_ERROR;
1999
2000 case MAILIMAP_SEARCH_KEY_RECENT:
2001 return mailimap_token_send(fd, "RECENT");
2002
2003 case MAILIMAP_SEARCH_KEY_SEEN:
2004 return mailimap_token_send(fd, "SEEN");
2005
2006 case MAILIMAP_SEARCH_KEY_SINCE:
2007 r = mailimap_token_send(fd, "SINCE");
2008 if (r != MAILIMAP_NO_ERROR)
2009 return r;
2010 r = mailimap_space_send(fd);
2011 if (r != MAILIMAP_NO_ERROR)
2012 return r;
2013 r = mailimap_date_send(fd, key->sk_data.sk_since);
2014 if (r != MAILIMAP_NO_ERROR)
2015 return r;
2016 return MAILIMAP_NO_ERROR;
2017
2018 case MAILIMAP_SEARCH_KEY_SUBJECT:
2019 r = mailimap_token_send(fd, "SUBJECT");
2020 if (r != MAILIMAP_NO_ERROR)
2021 return r;
2022 r = mailimap_space_send(fd);
2023 if (r != MAILIMAP_NO_ERROR)
2024 return r;
2025 r = mailimap_astring_send(fd, key->sk_data.sk_subject);
2026 if (r != MAILIMAP_NO_ERROR)
2027 return r;
2028 return MAILIMAP_NO_ERROR;
2029
2030 case MAILIMAP_SEARCH_KEY_TEXT:
2031 r = mailimap_token_send(fd, "TEXT");
2032 if (r != MAILIMAP_NO_ERROR)
2033 return r;
2034 r = mailimap_space_send(fd);
2035 if (r != MAILIMAP_NO_ERROR)
2036 return r;
2037 r = mailimap_astring_send(fd, key->sk_data.sk_text);
2038 if (r != MAILIMAP_NO_ERROR)
2039 return r;
2040 return MAILIMAP_NO_ERROR;
2041
2042 case MAILIMAP_SEARCH_KEY_TO:
2043 r = mailimap_token_send(fd, "TO");
2044 if (r != MAILIMAP_NO_ERROR)
2045 return r;
2046 r = mailimap_space_send(fd);
2047 if (r != MAILIMAP_NO_ERROR)
2048 return r;
2049 r = mailimap_astring_send(fd, key->sk_data.sk_text);
2050 if (r != MAILIMAP_NO_ERROR)
2051 return r;
2052 return MAILIMAP_NO_ERROR;
2053
2054 case MAILIMAP_SEARCH_KEY_UNANSWERED:
2055 return mailimap_token_send(fd, "UNANSWERED");
2056
2057 case MAILIMAP_SEARCH_KEY_UNDELETED:
2058 return mailimap_token_send(fd, "UNDELETED");
2059
2060 case MAILIMAP_SEARCH_KEY_UNFLAGGED:
2061 return mailimap_token_send(fd, "UNFLAGGED");
2062
2063 case MAILIMAP_SEARCH_KEY_UNKEYWORD:
2064 r = mailimap_token_send(fd, "UNKEYWORD");
2065 if (r != MAILIMAP_NO_ERROR)
2066 return r;
2067 r = mailimap_space_send(fd);
2068 if (r != MAILIMAP_NO_ERROR)
2069 return r;
2070 r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword);
2071 if (r != MAILIMAP_NO_ERROR)
2072 return r;
2073 return MAILIMAP_NO_ERROR;
2074
2075 case MAILIMAP_SEARCH_KEY_UNSEEN:
2076 return mailimap_token_send(fd, "UNSEEN");
2077
2078 case MAILIMAP_SEARCH_KEY_DRAFT:
2079 return mailimap_token_send(fd, "DRAFT");
2080
2081 case MAILIMAP_SEARCH_KEY_HEADER:
2082 r = mailimap_token_send(fd, "HEADER");
2083 if (r != MAILIMAP_NO_ERROR)
2084 return r;
2085 r = mailimap_space_send(fd);
2086 if (r != MAILIMAP_NO_ERROR)
2087 return r;
2088 r = mailimap_header_fld_name_send(fd,
2089 key->sk_data.sk_header.sk_header_name);
2090 if (r != MAILIMAP_NO_ERROR)
2091 return r;
2092 r = mailimap_space_send(fd);
2093 if (r != MAILIMAP_NO_ERROR)
2094 return r;
2095 r = mailimap_astring_send(fd,
2096 key->sk_data.sk_header.sk_header_value);
2097 if (r != MAILIMAP_NO_ERROR)
2098 return r;
2099 return MAILIMAP_NO_ERROR;
2100
2101 case MAILIMAP_SEARCH_KEY_LARGER:
2102 r = mailimap_token_send(fd, "LARGER");
2103 if (r != MAILIMAP_NO_ERROR)
2104 return r;
2105 r = mailimap_space_send(fd);
2106 if (r != MAILIMAP_NO_ERROR)
2107 return r;
2108 r = mailimap_number_send(fd, key->sk_data.sk_larger);
2109 if (r != MAILIMAP_NO_ERROR)
2110 return r;
2111 return MAILIMAP_NO_ERROR;
2112
2113 case MAILIMAP_SEARCH_KEY_NOT:
2114 r = mailimap_token_send(fd, "NOT");
2115 if (r != MAILIMAP_NO_ERROR)
2116 return r;
2117 r = mailimap_space_send(fd);
2118 if (r != MAILIMAP_NO_ERROR)
2119 return r;
2120 r = mailimap_search_key_send(fd, key->sk_data.sk_not);
2121 if (r != MAILIMAP_NO_ERROR)
2122 return r;
2123 return MAILIMAP_NO_ERROR;
2124
2125 case MAILIMAP_SEARCH_KEY_OR:
2126 r = mailimap_token_send(fd, "OR");
2127 if (r != MAILIMAP_NO_ERROR)
2128 return r;
2129 r = mailimap_space_send(fd);
2130 if (r != MAILIMAP_NO_ERROR)
2131 return r;
2132 r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or1);
2133 if (r != MAILIMAP_NO_ERROR)
2134 return r;
2135 r = mailimap_space_send(fd);
2136 if (r != MAILIMAP_NO_ERROR)
2137 return r;
2138 r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or2);
2139 if (r != MAILIMAP_NO_ERROR)
2140 return r;
2141 return TRUE;
2142
2143 case MAILIMAP_SEARCH_KEY_SENTBEFORE:
2144 r = mailimap_token_send(fd, "SENTBEFORE");
2145 if (r != MAILIMAP_NO_ERROR)
2146 return r;
2147 r = mailimap_space_send(fd);
2148 if (r != MAILIMAP_NO_ERROR)
2149 return r;
2150 r = mailimap_date_send(fd, key->sk_data.sk_sentbefore);
2151 if (r != MAILIMAP_NO_ERROR)
2152 return r;
2153 return MAILIMAP_NO_ERROR;
2154
2155 case MAILIMAP_SEARCH_KEY_SENTON:
2156 r = mailimap_token_send(fd, "SENTON");
2157 if (r != MAILIMAP_NO_ERROR)
2158 return r;
2159 r = mailimap_space_send(fd);
2160 if (r != MAILIMAP_NO_ERROR)
2161 return r;
2162 r = mailimap_date_send(fd, key->sk_data.sk_senton);
2163 if (r != MAILIMAP_NO_ERROR)
2164 return r;
2165 return MAILIMAP_NO_ERROR;
2166
2167 case MAILIMAP_SEARCH_KEY_SENTSINCE:
2168 r = mailimap_token_send(fd, "SENTSINCE");
2169 if (r != MAILIMAP_NO_ERROR)
2170 return r;
2171 r = mailimap_space_send(fd);
2172 if (r != MAILIMAP_NO_ERROR)
2173 return r;
2174 r = mailimap_date_send(fd, key->sk_data.sk_sentsince);
2175 if (r != MAILIMAP_NO_ERROR)
2176 return r;
2177 return MAILIMAP_NO_ERROR;
2178
2179 case MAILIMAP_SEARCH_KEY_SMALLER:
2180 r = mailimap_token_send(fd, "SMALLER");
2181 if (r != MAILIMAP_NO_ERROR)
2182 return r;
2183 r = mailimap_space_send(fd);
2184 if (r != MAILIMAP_NO_ERROR)
2185 return r;
2186 r = mailimap_number_send(fd, key->sk_data.sk_smaller);
2187 if (r != MAILIMAP_NO_ERROR)
2188 return r;
2189 return MAILIMAP_NO_ERROR;
2190
2191 case MAILIMAP_SEARCH_KEY_UID:
2192 r = mailimap_token_send(fd, "UID");
2193 if (r != MAILIMAP_NO_ERROR)
2194 return r;
2195 r = mailimap_space_send(fd);
2196 if (r != MAILIMAP_NO_ERROR)
2197 return r;
2198 r = mailimap_set_send(fd, key->sk_data.sk_set);
2199 if (r != MAILIMAP_NO_ERROR)
2200 return r;
2201 return MAILIMAP_NO_ERROR;
2202
2203 case MAILIMAP_SEARCH_KEY_UNDRAFT:
2204 return mailimap_token_send(fd, "UNDRAFT");
2205
2206 case MAILIMAP_SEARCH_KEY_SET:
2207 return mailimap_set_send(fd, key->sk_data.sk_set);
2208
2209 case MAILIMAP_SEARCH_KEY_MULTIPLE:
2210 r = mailimap_oparenth_send(fd);
2211 if (r != MAILIMAP_NO_ERROR)
2212 return r;
2213
2214 r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple,
2215 (mailimap_struct_sender *)
2216 mailimap_search_key_send);
2217 if (r != MAILIMAP_NO_ERROR)
2218 return r;
2219
2220 r = mailimap_cparenth_send(fd);
2221 if (r != MAILIMAP_NO_ERROR)
2222 return r;
2223
2224 return MAILIMAP_NO_ERROR;
2225 default:
2226 /* should not happend */
2227 return MAILIMAP_ERROR_INVAL;
2228 }
2229}
2230
2231/*
2232=> section = "[" [section-spec] "]"
2233*/
2234
2235static int
2236mailimap_section_send(mailstream * fd,
2237 struct mailimap_section * section)
2238{
2239 int r;
2240
2241 r = mailimap_char_send(fd, '[');
2242 if (r != MAILIMAP_NO_ERROR)
2243 return r;
2244
2245 if (section != NULL) {
2246 if (section->sec_spec != NULL) {
2247 r = mailimap_section_spec_send(fd, section->sec_spec);
2248 if (r != MAILIMAP_NO_ERROR)
2249 return r;
2250 }
2251 }
2252
2253 r = mailimap_char_send(fd, ']');
2254 if (r != MAILIMAP_NO_ERROR)
2255 return r;
2256
2257 return MAILIMAP_NO_ERROR;
2258}
2259
2260/*
2261=> section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
2262 "TEXT"
2263 ; top-level or MESSAGE/RFC822 part
2264*/
2265
2266static int
2267mailimap_section_msgtext_send(mailstream * fd,
2268 struct mailimap_section_msgtext *
2269 section_msgtext)
2270{
2271 int r;
2272
2273 switch (section_msgtext->sec_type) {
2274 case MAILIMAP_SECTION_MSGTEXT_HEADER:
2275 return mailimap_token_send(fd, "HEADER");
2276
2277 case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS:
2278 r = mailimap_token_send(fd, "HEADER.FIELDS");
2279 if (r != MAILIMAP_NO_ERROR)
2280 return r;
2281 r = mailimap_space_send(fd);
2282 if (r != MAILIMAP_NO_ERROR)
2283 return r;
2284 r = mailimap_header_list_send(fd, section_msgtext->sec_header_list);
2285 if (r != MAILIMAP_NO_ERROR)
2286 return r;
2287 return MAILIMAP_NO_ERROR;
2288
2289 case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT:
2290 r = mailimap_token_send(fd, "HEADER.FIELDS.NOT");
2291 if (r != MAILIMAP_NO_ERROR)
2292 return r;
2293 r = mailimap_space_send(fd);
2294 if (r != MAILIMAP_NO_ERROR)
2295 return r;
2296 r = mailimap_header_list_send(fd, section_msgtext->sec_header_list);
2297 if (r != MAILIMAP_NO_ERROR)
2298 return r;
2299 return MAILIMAP_NO_ERROR;
2300
2301 case MAILIMAP_SECTION_MSGTEXT_TEXT:
2302 return mailimap_token_send(fd, "TEXT");
2303
2304 default:
2305 /* should not happend */
2306 return MAILIMAP_ERROR_INVAL;
2307 }
2308}
2309
2310/*
2311=> section-part = nz-number *("." nz-number)
2312 ; body part nesting
2313*/
2314
2315static int
2316mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber)
2317{
2318 return mailimap_number_send(fd, * pnumber);
2319}
2320
2321static int
2322mailimap_section_part_send(mailstream * fd,
2323 struct mailimap_section_part * section)
2324{
2325 int r;
2326
2327 r = mailimap_struct_list_send(fd, section->sec_id, '.',
2328 (mailimap_struct_sender *) mailimap_pnumber_send);
2329 if (r != MAILIMAP_NO_ERROR)
2330 return r;
2331
2332 return MAILIMAP_NO_ERROR;
2333}
2334
2335/*
2336=> section-spec = section-msgtext / (section-part ["." section-text])
2337*/
2338
2339static int
2340mailimap_section_spec_send(mailstream * fd,
2341 struct mailimap_section_spec * section_spec)
2342{
2343 int r;
2344
2345 switch (section_spec->sec_type) {
2346 case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT:
2347 return mailimap_section_msgtext_send(fd,
2348 section_spec->sec_data.sec_msgtext);
2349
2350 case MAILIMAP_SECTION_SPEC_SECTION_PART:
2351 r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part);
2352 if (r != MAILIMAP_NO_ERROR)
2353 return r;
2354
2355 if (section_spec->sec_text != NULL) {
2356 r = mailimap_char_send(fd, '.');
2357 if (r != MAILIMAP_NO_ERROR)
2358 return r;
2359 r = mailimap_section_text_send(fd,
2360 section_spec->sec_text);
2361 if (r != MAILIMAP_NO_ERROR)
2362 return r;
2363 }
2364
2365 return MAILIMAP_NO_ERROR;
2366
2367 default:
2368 /* should not happen */
2369 return MAILIMAP_ERROR_INVAL;
2370 }
2371}
2372
2373/*
2374=> section-text = section-msgtext / "MIME"
2375 ; text other than actual body part (headers, etc.)
2376*/
2377
2378static int
2379mailimap_section_text_send(mailstream * fd,
2380 struct mailimap_section_text * section_text)
2381{
2382 switch (section_text->sec_type) {
2383 case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT:
2384 return mailimap_section_msgtext_send(fd, section_text->sec_msgtext);
2385
2386 case MAILIMAP_SECTION_TEXT_MIME:
2387 return mailimap_token_send(fd, "MIME");
2388
2389 default:
2390 /* should not happen */
2391 return MAILIMAP_NO_ERROR;
2392 }
2393}
2394
2395/*
2396=> select = "SELECT" SP mailbox
2397*/
2398
2399int
2400mailimap_select_send(mailstream * fd, const char * mb)
2401{
2402 int r;
2403
2404 r = mailimap_token_send(fd, "SELECT");
2405 if (r != MAILIMAP_NO_ERROR)
2406 return r;
2407 r = mailimap_space_send(fd);
2408 if (r != MAILIMAP_NO_ERROR)
2409 return r;
2410 r = mailimap_mailbox_send(fd, mb);
2411 if (r != MAILIMAP_NO_ERROR)
2412 return r;
2413
2414 return MAILIMAP_NO_ERROR;
2415}
2416
2417/*
2418=> sequence-num = nz-number / "*"
2419 ; * is the largest number in use. For message
2420 ; sequence numbers, it is the number of messages
2421 ; in the mailbox. For unique identifiers, it is
2422 ; the unique identifier of the last message in
2423 ; the mailbox.
2424*/
2425
2426/* if sequence_num == 0 then "*" */
2427
2428static int
2429mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num)
2430{
2431 if (sequence_num == 0)
2432 return mailimap_char_send(fd, '*');
2433 else
2434 return mailimap_number_send(fd, sequence_num);
2435}
2436
2437/*
2438=> set = sequence-num / (sequence-num ":" sequence-num) /
2439 (set "," set)
2440 ; Identifies a set of messages. For message
2441 ; sequence numbers, these are consecutive
2442 ; numbers from 1 to the number of messages in
2443 ; the mailbox
2444 ; Comma delimits individual numbers, colon
2445 ; delimits between two numbers inclusive.
2446 ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
2447 ; 14,15 for a mailbox with 15 messages.
2448*/
2449
2450static int mailimap_set_item_send(mailstream * fd,
2451 struct mailimap_set_item * item)
2452{
2453 int r;
2454
2455 if (item->set_first == item->set_last)
2456 return mailimap_sequence_num_send(fd, item->set_first);
2457 else {
2458 r = mailimap_sequence_num_send(fd, item->set_first);
2459 if (r != MAILIMAP_NO_ERROR)
2460 return r;
2461 r = mailimap_char_send(fd, ':');
2462 if (r != MAILIMAP_NO_ERROR)
2463 return r;
2464 r = mailimap_sequence_num_send(fd, item->set_last);
2465 if (r != MAILIMAP_NO_ERROR)
2466 return r;
2467 return MAILIMAP_NO_ERROR;
2468 }
2469}
2470
2471static int mailimap_set_send(mailstream * fd,
2472 struct mailimap_set * set)
2473{
2474 return mailimap_struct_list_send(fd, set->set_list, ',',
2475 (mailimap_struct_sender *) mailimap_set_item_send);
2476}
2477
2478/*
2479=> status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
2480*/
2481
2482static int
2483mailimap_status_att_list_send(mailstream * fd,
2484 struct mailimap_status_att_list * status_att_list)
2485{
2486 return mailimap_struct_spaced_list_send(fd, status_att_list->att_list,
2487 (mailimap_struct_sender *) mailimap_status_att_send);
2488}
2489
2490int
2491mailimap_status_send(mailstream * fd, const char * mb,
2492 struct mailimap_status_att_list * status_att_list)
2493{
2494 int r;
2495
2496 r = mailimap_token_send(fd, "STATUS");
2497 if (r != MAILIMAP_NO_ERROR)
2498 return r;
2499
2500 r = mailimap_space_send(fd);
2501 if (r != MAILIMAP_NO_ERROR)
2502 return r;
2503
2504 r = mailimap_mailbox_send(fd, mb);
2505 if (r != MAILIMAP_NO_ERROR)
2506 return r;
2507
2508 r = mailimap_space_send(fd);
2509 if (r != MAILIMAP_NO_ERROR)
2510 return r;
2511
2512 r = mailimap_char_send(fd, '(');
2513 if (r != MAILIMAP_NO_ERROR)
2514 return r;
2515
2516 r = mailimap_status_att_list_send(fd, status_att_list);
2517 if (r != MAILIMAP_NO_ERROR)
2518 return r;
2519
2520 r = mailimap_char_send(fd, ')');
2521 if (r != MAILIMAP_NO_ERROR)
2522 return r;
2523
2524 return MAILIMAP_NO_ERROR;
2525}
2526
2527/*
2528=> status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
2529 "UNSEEN"
2530*/
2531
2532
2533static int mailimap_status_att_send(mailstream * fd, int * status_att)
2534{
2535 const char * token;
2536
2537 token = mailimap_status_att_get_token_str(* status_att);
2538 if (token == NULL) {
2539 /* should not happen */
2540 return MAILIMAP_ERROR_INVAL;
2541 }
2542
2543 return mailimap_token_send(fd, token);
2544}
2545
2546/*
2547=> store = "STORE" SP set SP store-att-flags
2548*/
2549
2550int
2551mailimap_store_send(mailstream * fd,
2552 struct mailimap_set * set,
2553 struct mailimap_store_att_flags * store_att_flags)
2554{
2555 int r;
2556
2557 r = mailimap_token_send(fd, "STORE");
2558 if (r != MAILIMAP_NO_ERROR)
2559 return r;
2560 r = mailimap_space_send(fd);
2561 if (r != MAILIMAP_NO_ERROR)
2562 return r;
2563 r = mailimap_set_send(fd, set);
2564 if (r != MAILIMAP_NO_ERROR)
2565 return r;
2566 r = mailimap_space_send(fd);
2567 if (r != MAILIMAP_NO_ERROR)
2568 return r;
2569
2570 r = mailimap_store_att_flags_send(fd, store_att_flags);
2571 if (r != MAILIMAP_NO_ERROR)
2572 return r;
2573
2574 return MAILIMAP_NO_ERROR;
2575}
2576
2577int
2578mailimap_uid_store_send(mailstream * fd,
2579 struct mailimap_set * set,
2580 struct mailimap_store_att_flags * store_att_flags)
2581{
2582 int r;
2583
2584 r = mailimap_token_send(fd, "UID");
2585 if (r != MAILIMAP_NO_ERROR)
2586 return r;
2587 r = mailimap_space_send(fd);
2588 if (r != MAILIMAP_NO_ERROR)
2589 return r;
2590
2591 return mailimap_store_send(fd, set, store_att_flags);
2592}
2593
2594/*
2595=> store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
2596 (flag-list / (flag *(SP flag)))
2597*/
2598
2599static int
2600mailimap_store_att_flags_send(mailstream * fd,
2601 struct mailimap_store_att_flags * store_flags)
2602{
2603 int r;
2604
2605 switch (store_flags->fl_sign) {
2606 case 1:
2607 r = mailimap_char_send(fd, '+');
2608 if (r != MAILIMAP_NO_ERROR)
2609 return r;
2610 case -1:
2611 r = mailimap_char_send(fd, '-');
2612 if (r != MAILIMAP_NO_ERROR)
2613 return r;
2614 }
2615
2616 r = mailimap_token_send(fd, "FLAGS");
2617 if (r != MAILIMAP_NO_ERROR)
2618 return r;
2619
2620 if (store_flags->fl_silent) {
2621 r = mailimap_token_send(fd, ".SILENT");
2622 if (r != MAILIMAP_NO_ERROR)
2623 return r;
2624 }
2625
2626 r = mailimap_space_send(fd);
2627 if (r != MAILIMAP_NO_ERROR)
2628 return r;
2629
2630 r = mailimap_flag_list_send(fd, store_flags->fl_flag_list);
2631 if (r != MAILIMAP_NO_ERROR)
2632 return r;
2633
2634 return MAILIMAP_NO_ERROR;
2635}
2636
2637/*
2638 string = quoted / literal
2639*/
2640
2641/*
2642=> subscribe = "SUBSCRIBE" SP mailbox
2643*/
2644
2645int mailimap_subscribe_send(mailstream * fd, const char * mb)
2646{
2647 int r;
2648
2649 r = mailimap_token_send(fd, "SUBSCRIBE");
2650 if (r != MAILIMAP_NO_ERROR)
2651 return r;
2652
2653 r = mailimap_space_send(fd);
2654 if (r != MAILIMAP_NO_ERROR)
2655 return r;
2656
2657 r = mailimap_mailbox_send(fd, mb);
2658 if (r != MAILIMAP_NO_ERROR)
2659 return r;
2660
2661 return MAILIMAP_NO_ERROR;
2662}
2663
2664/*
2665=> tag = 1*<any ASTRING-CHAR except "+">
2666*/
2667
2668int mailimap_tag_send(mailstream * fd, const char * tag)
2669{
2670 return mailimap_token_send(fd, tag);
2671}
2672
2673/*
2674 text = 1*TEXT-CHAR
2675
2676 TEXT-CHAR = <any CHAR except CR and LF>
2677
2678 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
2679 ; Hours minutes seconds
2680*/
2681
2682/*
2683=> uid = "UID" SP (copy / fetch / search / store)
2684 ; Unique identifiers used instead of message
2685 ; sequence numbers
2686
2687functions uid_copy, uid_fetch ...
2688*/
2689
2690
2691/*
2692 uniqueid = nz-number
2693 ; Strictly ascending
2694*/
2695
2696/*
2697=> unsubscribe = "UNSUBSCRIBE" SP mailbox
2698*/
2699
2700int mailimap_unsubscribe_send(mailstream * fd,
2701 const char * mb)
2702{
2703 int r;
2704
2705 r = mailimap_token_send(fd, "UNSUBSCRIBE");
2706 if (r != MAILIMAP_NO_ERROR)
2707 return r;
2708 r = mailimap_space_send(fd);
2709 if (r != MAILIMAP_NO_ERROR)
2710 return r;
2711 r = mailimap_mailbox_send(fd, mb);
2712 if (r != MAILIMAP_NO_ERROR)
2713 return r;
2714
2715 return MAILIMAP_NO_ERROR;
2716}
2717
2718int mailimap_starttls_send(mailstream * fd)
2719{
2720 return mailimap_token_send(fd, "STARTTLS");
2721}
2722
2723/*
2724=> userid = astring
2725*/
2726
2727static int mailimap_userid_send(mailstream * fd, const char * user)
2728{
2729 return mailimap_astring_send(fd, user);
2730}
2731
2732/*
2733 x-command = "X" atom <experimental command arguments>
2734
2735 zone = ("+" / "-") 4DIGIT
2736 ; Signed four-digit value of hhmm representing
2737 ; hours and minutes east of Greenwich (that is,
2738 ; the amount that the given time differs from
2739 ; Universal Time). Subtracting the timezone
2740 ; from the given time will give the UT form.
2741 ; The Universal Time zone is "+0000".
2742*/
diff --git a/libetpan/src/low-level/imap/mailimap_sender.h b/libetpan/src/low-level/imap/mailimap_sender.h
new file mode 100644
index 0000000..34661f5
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_sender.h
@@ -0,0 +1,164 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_SENDER_H
37
38#define MAILIMAP_SENDER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailimap_types.h"
45
46int mailimap_append_send(mailstream * fd,
47 const char * mailbox,
48 struct mailimap_flag_list * flag_list,
49 struct mailimap_date_time * date_time,
50 size_t literal_size);
51
52int mailimap_authenticate_send(mailstream * fd,
53 const char * auth_type);
54
55int mailimap_authenticate_resp_send(mailstream * fd,
56 const char * base64);
57
58int mailimap_noop_send(mailstream * fd);
59
60int mailimap_logout_send(mailstream * fd);
61
62int mailimap_capability_send(mailstream * fd);
63
64int mailimap_check_send(mailstream * fd);
65
66int mailimap_close_send(mailstream * fd);
67
68int mailimap_expunge_send(mailstream * fd);
69
70int mailimap_copy_send(mailstream * fd,
71 struct mailimap_set * set,
72 const char * mb);
73
74int mailimap_uid_copy_send(mailstream * fd,
75 struct mailimap_set * set,
76 const char * mb);
77
78int mailimap_create_send(mailstream * fd,
79 const char * mb);
80
81
82int mailimap_delete_send(mailstream * fd, const char * mb);
83
84int mailimap_examine_send(mailstream * fd, const char * mb);
85
86int
87mailimap_fetch_send(mailstream * fd,
88 struct mailimap_set * set,
89 struct mailimap_fetch_type * fetch_type);
90
91int
92mailimap_uid_fetch_send(mailstream * fd,
93 struct mailimap_set * set,
94 struct mailimap_fetch_type * fetch_type);
95
96int mailimap_list_send(mailstream * fd,
97 const char * mb, const char * list_mb);
98
99int mailimap_login_send(mailstream * fd,
100 const char * userid, const char * password);
101
102int mailimap_lsub_send(mailstream * fd,
103 const char * mb, const char * list_mb);
104
105int mailimap_rename_send(mailstream * fd, const char * mb,
106 const char * new_name);
107
108int
109mailimap_search_send(mailstream * fd, const char * charset,
110 struct mailimap_search_key * key);
111
112int
113mailimap_uid_search_send(mailstream * fd, const char * charset,
114 struct mailimap_search_key * key);
115
116int
117mailimap_select_send(mailstream * fd, const char * mb);
118
119int
120mailimap_status_send(mailstream * fd, const char * mb,
121 struct mailimap_status_att_list * status_att_list);
122
123int
124mailimap_store_send(mailstream * fd,
125 struct mailimap_set * set,
126 struct mailimap_store_att_flags * store_att_flags);
127
128int
129mailimap_uid_store_send(mailstream * fd,
130 struct mailimap_set * set,
131 struct mailimap_store_att_flags * store_att_flags);
132
133int mailimap_subscribe_send(mailstream * fd, const char * mb);
134
135
136int mailimap_tag_send(mailstream * fd, const char * tag);
137
138int mailimap_unsubscribe_send(mailstream * fd,
139 const char * mb);
140
141int mailimap_crlf_send(mailstream * fd);
142
143int mailimap_space_send(mailstream * fd);
144
145int
146mailimap_literal_send(mailstream * fd, const char * literal,
147 size_t progr_rate,
148 progress_function * progr_fun);
149
150int
151mailimap_literal_count_send(mailstream * fd, uint32_t count);
152
153int
154mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len,
155 size_t progr_rate,
156 progress_function * progr_fun);
157
158int mailimap_starttls_send(mailstream * fd);
159
160#ifdef __cplusplus
161}
162#endif
163
164#endif
diff --git a/libetpan/src/low-level/imap/mailimap_socket.c b/libetpan/src/low-level/imap/mailimap_socket.c
new file mode 100644
index 0000000..01070b1
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_socket.c
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_socket.h"
37
38#include "mailimap.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_IMAP_PORT 143
45#define SERVICE_NAME_IMAP "imap2"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port)
49{
50 int s;
51 mailstream * stream;
52
53 if (port == 0) {
54 port = mail_get_service_port(SERVICE_NAME_IMAP, SERVICE_TYPE_TCP);
55 if (port == 0)
56 port = DEFAULT_IMAP_PORT;
57 port = ntohs(port);
58 }
59
60 /* Connection */
61
62 s = mail_tcp_connect(server, port);
63 if (s == -1)
64 return MAILIMAP_ERROR_CONNECTION_REFUSED;
65
66 stream = mailstream_socket_open(s);
67 if (stream == NULL) {
68 close(s);
69 return MAILIMAP_ERROR_MEMORY;
70 }
71
72 return mailimap_connect(f, stream);
73}
diff --git a/libetpan/src/low-level/imap/mailimap_socket.h b/libetpan/src/low-level/imap/mailimap_socket.h
new file mode 100644
index 0000000..ed8f369
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_socket.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_SOCKET_H
37
38#define MAILIMAP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailimap_types.h>
47
48int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/low-level/imap/mailimap_ssl.c b/libetpan/src/low-level/imap/mailimap_ssl.c
new file mode 100644
index 0000000..44ae36e
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_ssl.c
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_ssl.h"
37
38#include "mailimap.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_IMAPS_PORT 993
45#define SERVICE_NAME_IMAPS "imaps"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port)
49{
50 int s;
51 mailstream * stream;
52
53 if (port == 0) {
54 port = mail_get_service_port(SERVICE_NAME_IMAPS, SERVICE_TYPE_TCP);
55 if (port == 0)
56 port = DEFAULT_IMAPS_PORT;
57 port = ntohs(port);
58 }
59
60 /* Connection */
61
62 s = mail_tcp_connect(server, port);
63 if (s == -1)
64 return MAILIMAP_ERROR_CONNECTION_REFUSED;
65
66 stream = mailstream_ssl_open(s);
67 if (stream == NULL) {
68 close(s);
69 return MAILIMAP_ERROR_CONNECTION_REFUSED;
70 }
71
72 return mailimap_connect(f, stream);
73}
diff --git a/libetpan/src/low-level/imap/mailimap_ssl.h b/libetpan/src/low-level/imap/mailimap_ssl.h
new file mode 100644
index 0000000..4d5146c
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_ssl.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_SSL_H
37
38#define MAILIMAP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailimap_types.h>
47
48int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/low-level/imap/mailimap_types.c b/libetpan/src/low-level/imap/mailimap_types.c
new file mode 100644
index 0000000..5889f32
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_types.c
@@ -0,0 +1,2961 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_types.h"
37#include "mmapstring.h"
38#include "mail.h"
39
40#include <stdlib.h>
41
42/* ************************************************************************* */
43/* ************************************************************************* */
44/* ************************************************************************* */
45/* ************************************************************************* */
46/* ************************************************************************* */
47/* ************************************************************************* */
48
49
50
51
52
53
54/* from parser */
55
56
57uint32_t * mailimap_number_alloc_new(uint32_t number)
58{
59 uint32_t * pnumber;
60
61 pnumber = malloc(sizeof(* pnumber));
62 if (pnumber == NULL)
63 return NULL;
64
65 * pnumber = number;
66
67 return pnumber;
68}
69
70void mailimap_number_alloc_free(uint32_t * pnumber)
71{
72 free(pnumber);
73}
74
75
76/* ************************************************************************* */
77
78
79struct mailimap_address *
80mailimap_address_new(char * ad_personal_name, char * ad_source_route,
81 char * ad_mailbox_name, char * ad_host_name)
82{
83 struct mailimap_address * addr;
84
85 addr = malloc(sizeof(* addr));
86 if (addr == NULL)
87 return NULL;
88
89 addr->ad_personal_name = ad_personal_name;
90 addr->ad_source_route = ad_source_route;
91 addr->ad_mailbox_name = ad_mailbox_name;
92 addr->ad_host_name = ad_host_name;
93
94 return addr;
95}
96
97void mailimap_address_free(struct mailimap_address * addr)
98{
99 mailimap_addr_host_free(addr->ad_host_name);
100 mailimap_addr_mailbox_free(addr->ad_mailbox_name);
101 mailimap_addr_adl_free(addr->ad_source_route);
102 mailimap_addr_name_free(addr->ad_personal_name);
103 free(addr);
104}
105
106void mailimap_addr_host_free(char * addr_host)
107{
108 mailimap_nstring_free(addr_host);
109}
110
111void mailimap_addr_mailbox_free(char * addr_mailbox)
112{
113 mailimap_nstring_free(addr_mailbox);
114}
115
116void mailimap_addr_adl_free(char * addr_adl)
117{
118 mailimap_nstring_free(addr_adl);
119}
120
121void mailimap_addr_name_free(char * addr_name)
122{
123 mailimap_nstring_free(addr_name);
124}
125
126
127
128
129
130/*
131struct mailimap_astring *
132mailimap_astring_new(gint type,
133 gchar * atom_astring,
134 gchar * string)
135{
136 struct mailimap_astring * astring;
137
138 astring = g_new(struct mailimap_astring, 1);
139 if (astring == NULL)
140 return FALSE;
141
142 astring->type = type;
143 astring->atom_astring = atom_astring;
144 astring->string = string;
145
146 return astring;
147}
148
149void mailimap_astring_free(struct mailimap_astring * astring)
150{
151 if (astring->atom_astring)
152 mailimap_atom_astring_free(astring->atom_astring);
153 if (astring->string)
154 mailimap_string_free(astring->string);
155 free(astring);
156}
157*/
158
159void mailimap_astring_free(char * astring)
160{
161 if (mmap_string_unref(astring) != 0)
162 free(astring);
163}
164
165static void mailimap_custom_string_free(char * str)
166{
167 free(str);
168}
169
170
171void mailimap_atom_free(char * atom)
172{
173 free(atom);
174}
175
176
177
178
179void mailimap_auth_type_free(char * auth_type)
180{
181 mailimap_atom_free(auth_type);
182}
183
184
185
186
187
188void mailimap_base64_free(char * base64)
189{
190 free(base64);
191}
192
193
194
195
196struct mailimap_body *
197mailimap_body_new(int bd_type,
198 struct mailimap_body_type_1part * bd_body_1part,
199 struct mailimap_body_type_mpart * bd_body_mpart)
200{
201 struct mailimap_body * body;
202
203 body = malloc(sizeof(* body));
204 if (body == NULL)
205 return NULL;
206
207 body->bd_type = bd_type;
208 switch (bd_type) {
209 case MAILIMAP_BODY_1PART:
210 body->bd_data.bd_body_1part = bd_body_1part;
211 break;
212 case MAILIMAP_BODY_MPART:
213 body->bd_data.bd_body_mpart = bd_body_mpart;
214 break;
215 }
216
217 return body;
218}
219
220void mailimap_body_free(struct mailimap_body * body)
221{
222 switch (body->bd_type) {
223 case MAILIMAP_BODY_1PART:
224 mailimap_body_type_1part_free(body->bd_data.bd_body_1part);
225 break;
226 case MAILIMAP_BODY_MPART:
227 mailimap_body_type_mpart_free(body->bd_data.bd_body_mpart);
228 break;
229 }
230 free(body);
231}
232
233
234struct mailimap_body_extension *
235mailimap_body_extension_new(int ext_type, char * ext_nstring,
236 uint32_t ext_number,
237 clist * ext_body_extension_list)
238{
239 struct mailimap_body_extension * body_extension;
240
241 body_extension = malloc(sizeof(* body_extension));
242 if (body_extension == NULL)
243 return NULL;
244
245 body_extension->ext_type = ext_type;
246 switch (ext_type) {
247 case MAILIMAP_BODY_EXTENSION_NSTRING:
248 body_extension->ext_data.ext_nstring = ext_nstring;
249 break;
250 case MAILIMAP_BODY_EXTENSION_NUMBER:
251 body_extension->ext_data.ext_number = ext_number;
252 break;
253 case MAILIMAP_BODY_EXTENSION_LIST:
254 body_extension->ext_data.ext_body_extension_list = ext_body_extension_list;
255 break;
256 }
257
258 return body_extension;
259}
260
261static void
262mailimap_body_ext_list_free(clist * body_ext_list);
263
264void mailimap_body_extension_free(struct mailimap_body_extension * be)
265{
266 switch (be->ext_type) {
267 case MAILIMAP_BODY_EXTENSION_NSTRING:
268 mailimap_nstring_free(be->ext_data.ext_nstring);
269 break;
270 case MAILIMAP_BODY_EXTENSION_LIST:
271 mailimap_body_ext_list_free(be->ext_data.ext_body_extension_list);
272 break;
273 }
274
275 free(be);
276}
277
278
279static void
280mailimap_body_ext_list_free(clist * body_ext_list)
281{
282 clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free,
283 NULL);
284 clist_free(body_ext_list);
285}
286
287
288struct mailimap_body_ext_1part *
289mailimap_body_ext_1part_new(char * bd_md5,
290 struct mailimap_body_fld_dsp * bd_disposition,
291 struct mailimap_body_fld_lang * bd_language,
292 clist * bd_extension_list)
293{
294 struct mailimap_body_ext_1part * body_ext_1part;
295
296 body_ext_1part = malloc(sizeof(* body_ext_1part));
297 if (body_ext_1part == NULL)
298 return NULL;
299
300 body_ext_1part->bd_md5 = bd_md5;
301 body_ext_1part->bd_disposition = bd_disposition;
302 body_ext_1part->bd_language = bd_language;
303 body_ext_1part->bd_extension_list = bd_extension_list;
304
305 return body_ext_1part;
306}
307
308void
309mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part)
310{
311 mailimap_body_fld_md5_free(body_ext_1part->bd_md5);
312 if (body_ext_1part->bd_disposition)
313 mailimap_body_fld_dsp_free(body_ext_1part->bd_disposition);
314 if (body_ext_1part->bd_language)
315 mailimap_body_fld_lang_free(body_ext_1part->bd_language);
316 if (body_ext_1part->bd_extension_list)
317 mailimap_body_ext_list_free(body_ext_1part->bd_extension_list);
318
319 free(body_ext_1part);
320}
321
322struct mailimap_body_ext_mpart *
323mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter,
324 struct mailimap_body_fld_dsp * bd_disposition,
325 struct mailimap_body_fld_lang * bd_language,
326 clist * bd_extension_list)
327{
328 struct mailimap_body_ext_mpart * body_ext_mpart;
329
330 body_ext_mpart = malloc(sizeof(* body_ext_mpart));
331 if (body_ext_mpart == NULL)
332 return NULL;
333
334 body_ext_mpart->bd_parameter = bd_parameter;
335 body_ext_mpart->bd_disposition = bd_disposition;
336 body_ext_mpart->bd_language = bd_language;
337 body_ext_mpart->bd_extension_list = bd_extension_list;
338
339 return body_ext_mpart;
340}
341
342void
343mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart)
344{
345 if (body_ext_mpart->bd_parameter != NULL)
346 mailimap_body_fld_param_free(body_ext_mpart->bd_parameter);
347 if (body_ext_mpart->bd_disposition)
348 mailimap_body_fld_dsp_free(body_ext_mpart->bd_disposition);
349 if (body_ext_mpart->bd_language)
350 mailimap_body_fld_lang_free(body_ext_mpart->bd_language);
351 if (body_ext_mpart->bd_extension_list)
352 mailimap_body_ext_list_free(body_ext_mpart->bd_extension_list);
353 free(body_ext_mpart);
354}
355
356
357struct mailimap_body_fields *
358mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter,
359 char * bd_id,
360 char * bd_description,
361 struct mailimap_body_fld_enc * bd_encoding,
362 uint32_t bd_size)
363{
364 struct mailimap_body_fields * body_fields;
365
366 body_fields = malloc(sizeof(* body_fields));
367 if (body_fields == NULL)
368 return NULL;
369 body_fields->bd_parameter = bd_parameter;
370 body_fields->bd_id = bd_id;
371 body_fields->bd_description = bd_description;
372 body_fields->bd_encoding = bd_encoding;
373 body_fields->bd_size = bd_size;
374
375 return body_fields;
376}
377
378void
379mailimap_body_fields_free(struct mailimap_body_fields * body_fields)
380{
381 if (body_fields->bd_parameter != NULL)
382 mailimap_body_fld_param_free(body_fields->bd_parameter);
383 mailimap_body_fld_id_free(body_fields->bd_id);
384 mailimap_body_fld_desc_free(body_fields->bd_description);
385 mailimap_body_fld_enc_free(body_fields->bd_encoding);
386 free(body_fields);
387}
388
389
390
391
392
393
394void mailimap_body_fld_desc_free(char * body_fld_desc)
395{
396 mailimap_nstring_free(body_fld_desc);
397}
398
399
400
401
402struct mailimap_body_fld_dsp *
403mailimap_body_fld_dsp_new(char * dsp_type,
404 struct mailimap_body_fld_param * dsp_attributes)
405{
406 struct mailimap_body_fld_dsp * body_fld_dsp;
407
408 body_fld_dsp = malloc(sizeof(* body_fld_dsp));
409 if (body_fld_dsp == NULL)
410 return NULL;
411
412 body_fld_dsp->dsp_type = dsp_type;
413 body_fld_dsp->dsp_attributes = dsp_attributes;
414
415 return body_fld_dsp;
416}
417
418void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd)
419{
420 if (bfd->dsp_type != NULL)
421 mailimap_string_free(bfd->dsp_type);
422 if (bfd->dsp_attributes != NULL)
423 mailimap_body_fld_param_free(bfd->dsp_attributes);
424 free(bfd);
425}
426
427
428
429struct mailimap_body_fld_enc *
430mailimap_body_fld_enc_new(int enc_type, char * enc_value)
431{
432 struct mailimap_body_fld_enc * body_fld_enc;
433
434 body_fld_enc = malloc(sizeof(* body_fld_enc));
435 if (body_fld_enc == NULL)
436 return NULL;
437
438 body_fld_enc->enc_type = enc_type;
439 body_fld_enc->enc_value = enc_value;
440
441 return body_fld_enc;
442}
443
444void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe)
445{
446 if (bfe->enc_value)
447 mailimap_string_free(bfe->enc_value);
448 free(bfe);
449}
450
451
452
453void mailimap_body_fld_id_free(char * body_fld_id)
454{
455 mailimap_nstring_free(body_fld_id);
456}
457
458
459
460struct mailimap_body_fld_lang *
461mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list)
462{
463 struct mailimap_body_fld_lang * fld_lang;
464
465 fld_lang = malloc(sizeof(* fld_lang));
466 if (fld_lang == NULL)
467 return NULL;
468
469 fld_lang->lg_type = lg_type;
470 switch (lg_type) {
471 case MAILIMAP_BODY_FLD_LANG_SINGLE:
472 fld_lang->lg_data.lg_single = lg_single;
473 break;
474 case MAILIMAP_BODY_FLD_LANG_LIST:
475 fld_lang->lg_data.lg_list = lg_list;
476 break;
477 }
478
479 return fld_lang;
480}
481
482void
483mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang)
484{
485 switch (fld_lang->lg_type) {
486 case MAILIMAP_BODY_FLD_LANG_SINGLE:
487 mailimap_nstring_free(fld_lang->lg_data.lg_single);
488 break;
489 case MAILIMAP_BODY_FLD_LANG_LIST:
490 clist_foreach(fld_lang->lg_data.lg_list,
491 (clist_func) mailimap_string_free, NULL);
492 clist_free(fld_lang->lg_data.lg_list);
493 break;
494 }
495 free(fld_lang);
496}
497
498
499
500void mailimap_body_fld_md5_free(char * body_fld_md5)
501{
502 mailimap_nstring_free(body_fld_md5);
503}
504
505
506
507struct mailimap_single_body_fld_param *
508mailimap_single_body_fld_param_new(char * pa_name, char * pa_value)
509{
510 struct mailimap_single_body_fld_param * param;
511
512 param = malloc(sizeof(* param));
513 if (param == NULL)
514 return NULL;
515 param->pa_name = pa_name;
516 param->pa_value = pa_value;
517
518 return param;
519}
520
521void
522mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p)
523{
524 mailimap_string_free(p->pa_name);
525 mailimap_string_free(p->pa_value);
526 free(p);
527}
528
529
530struct mailimap_body_fld_param *
531mailimap_body_fld_param_new(clist * pa_list)
532{
533 struct mailimap_body_fld_param * fld_param;
534
535 fld_param = malloc(sizeof(* fld_param));
536 if (fld_param == NULL)
537 return NULL;
538 fld_param->pa_list = pa_list;
539
540 return fld_param;
541}
542
543void
544mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param)
545{
546 clist_foreach(fld_param->pa_list,
547 (clist_func) mailimap_single_body_fld_param_free, NULL);
548 clist_free(fld_param->pa_list);
549 free(fld_param);
550}
551
552
553struct mailimap_body_type_1part *
554mailimap_body_type_1part_new(int bd_type,
555 struct mailimap_body_type_basic * bd_type_basic,
556 struct mailimap_body_type_msg * bd_type_msg,
557 struct mailimap_body_type_text * bd_type_text,
558 struct mailimap_body_ext_1part * bd_ext_1part)
559{
560 struct mailimap_body_type_1part * body_type_1part;
561
562 body_type_1part = malloc(sizeof(* body_type_1part));
563 if (body_type_1part == NULL)
564 return NULL;
565
566 body_type_1part->bd_type = bd_type;
567 switch (bd_type) {
568 case MAILIMAP_BODY_TYPE_1PART_BASIC:
569 body_type_1part->bd_data.bd_type_basic = bd_type_basic;
570 break;
571 case MAILIMAP_BODY_TYPE_1PART_MSG:
572 body_type_1part->bd_data.bd_type_msg = bd_type_msg;
573 break;
574 case MAILIMAP_BODY_TYPE_1PART_TEXT:
575 body_type_1part->bd_data.bd_type_text = bd_type_text;
576 break;
577 }
578 body_type_1part->bd_ext_1part = bd_ext_1part;
579
580 return body_type_1part;
581}
582
583void
584mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p)
585{
586 switch (bt1p->bd_type) {
587 case MAILIMAP_BODY_TYPE_1PART_BASIC:
588 mailimap_body_type_basic_free(bt1p->bd_data.bd_type_basic);
589 break;
590 case MAILIMAP_BODY_TYPE_1PART_MSG:
591 mailimap_body_type_msg_free(bt1p->bd_data.bd_type_msg);
592 break;
593 case MAILIMAP_BODY_TYPE_1PART_TEXT:
594 mailimap_body_type_text_free(bt1p->bd_data.bd_type_text);
595 break;
596 }
597 if (bt1p->bd_ext_1part)
598 mailimap_body_ext_1part_free(bt1p->bd_ext_1part);
599
600 free(bt1p);
601}
602
603
604
605struct mailimap_body_type_basic *
606mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic,
607 struct mailimap_body_fields * bd_fields)
608{
609 struct mailimap_body_type_basic * body_type_basic;
610
611 body_type_basic = malloc(sizeof(* body_type_basic));
612 if (body_type_basic == NULL)
613 return NULL;
614
615 body_type_basic->bd_media_basic = bd_media_basic;
616 body_type_basic->bd_fields = bd_fields;
617
618 return body_type_basic;
619}
620
621void mailimap_body_type_basic_free(struct mailimap_body_type_basic *
622 body_type_basic)
623{
624 mailimap_media_basic_free(body_type_basic->bd_media_basic);
625 mailimap_body_fields_free(body_type_basic->bd_fields);
626 free(body_type_basic);
627}
628
629
630struct mailimap_body_type_mpart *
631mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype,
632 struct mailimap_body_ext_mpart * bd_ext_mpart)
633{
634 struct mailimap_body_type_mpart * body_type_mpart;
635
636 body_type_mpart = malloc(sizeof(* body_type_mpart));
637 if (body_type_mpart == NULL)
638 return NULL;
639
640 body_type_mpart->bd_list = bd_list;
641 body_type_mpart->bd_media_subtype = bd_media_subtype;
642 body_type_mpart->bd_ext_mpart = bd_ext_mpart;
643
644 return body_type_mpart;
645}
646
647void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart *
648 body_type_mpart)
649{
650 clist_foreach(body_type_mpart->bd_list,
651 (clist_func) mailimap_body_free, NULL);
652 clist_free(body_type_mpart->bd_list);
653 mailimap_media_subtype_free(body_type_mpart->bd_media_subtype);
654 if (body_type_mpart->bd_ext_mpart)
655 mailimap_body_ext_mpart_free(body_type_mpart->bd_ext_mpart);
656
657 free(body_type_mpart);
658}
659
660
661struct mailimap_body_type_msg *
662mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields,
663 struct mailimap_envelope * bd_envelope,
664 struct mailimap_body * bd_body,
665 uint32_t bd_lines)
666{
667 struct mailimap_body_type_msg * body_type_msg;
668
669 body_type_msg = malloc(sizeof(* body_type_msg));
670 if (body_type_msg == NULL)
671 return NULL;
672
673 body_type_msg->bd_fields = bd_fields;
674 body_type_msg->bd_envelope = bd_envelope;
675 body_type_msg->bd_body = bd_body;
676 body_type_msg->bd_lines = bd_lines;
677
678 return body_type_msg;
679}
680
681void
682mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg)
683{
684 mailimap_body_fields_free(body_type_msg->bd_fields);
685 mailimap_envelope_free(body_type_msg->bd_envelope);
686 mailimap_body_free(body_type_msg->bd_body);
687 free(body_type_msg);
688}
689
690
691
692struct mailimap_body_type_text *
693mailimap_body_type_text_new(char * bd_media_text,
694 struct mailimap_body_fields * bd_fields,
695 uint32_t bd_lines)
696{
697 struct mailimap_body_type_text * body_type_text;
698
699 body_type_text = malloc(sizeof(* body_type_text));
700 if (body_type_text == NULL)
701 return NULL;
702
703 body_type_text->bd_media_text = bd_media_text;
704 body_type_text->bd_fields = bd_fields;
705 body_type_text->bd_lines = bd_lines;
706
707 return body_type_text;
708}
709
710void
711mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text)
712{
713 mailimap_media_text_free(body_type_text->bd_media_text);
714 mailimap_body_fields_free(body_type_text->bd_fields);
715 free(body_type_text);
716}
717
718
719
720struct mailimap_capability *
721mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name)
722{
723 struct mailimap_capability * cap;
724
725 cap = malloc(sizeof(* cap));
726 if (cap == NULL)
727 return NULL;
728 cap->cap_type = cap_type;
729 switch (cap_type) {
730 case MAILIMAP_CAPABILITY_AUTH_TYPE:
731 cap->cap_data.cap_auth_type = cap_auth_type;
732 break;
733 case MAILIMAP_CAPABILITY_NAME:
734 cap->cap_data.cap_name = cap_name;
735 break;
736 }
737
738 return cap;
739}
740
741void mailimap_capability_free(struct mailimap_capability * c)
742{
743 switch (c->cap_type) {
744 case MAILIMAP_CAPABILITY_AUTH_TYPE:
745 free(c->cap_data.cap_auth_type);
746 break;
747 case MAILIMAP_CAPABILITY_NAME:
748 free(c->cap_data.cap_name);
749 break;
750 }
751 free(c);
752}
753
754
755struct mailimap_capability_data *
756mailimap_capability_data_new(clist * cap_list)
757{
758 struct mailimap_capability_data * cap_data;
759
760 cap_data = malloc(sizeof(* cap_data));
761 if (cap_data == NULL)
762 return NULL;
763
764 cap_data->cap_list = cap_list;
765
766 return cap_data;
767}
768
769void
770mailimap_capability_data_free(struct mailimap_capability_data * cap_data)
771{
772 if (cap_data->cap_list) {
773 clist_foreach(cap_data->cap_list,
774 (clist_func) mailimap_capability_free, NULL);
775 clist_free(cap_data->cap_list);
776 }
777 free(cap_data);
778}
779
780
781
782
783struct mailimap_continue_req *
784mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text,
785 char * cr_base64)
786{
787 struct mailimap_continue_req * cont_req;
788
789 cont_req = malloc(sizeof(* cont_req));
790 if (cont_req == NULL)
791 return NULL;
792 cont_req->cr_type = cr_type;
793 switch (cr_type) {
794 case MAILIMAP_CONTINUE_REQ_TEXT:
795 cont_req->cr_data.cr_text = cr_text;
796 break;
797 case MAILIMAP_CONTINUE_REQ_BASE64:
798 cont_req->cr_data.cr_base64 = cr_base64;
799 break;
800 }
801
802 return cont_req;
803}
804
805void mailimap_continue_req_free(struct mailimap_continue_req * cont_req)
806{
807 switch (cont_req->cr_type) {
808 case MAILIMAP_CONTINUE_REQ_TEXT:
809 mailimap_resp_text_free(cont_req->cr_data.cr_text);
810 break;
811 case MAILIMAP_CONTINUE_REQ_BASE64:
812 mailimap_base64_free(cont_req->cr_data.cr_base64);
813 break;
814 }
815 free(cont_req);
816}
817
818struct mailimap_date_time *
819mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour,
820 int dt_min, int dt_sec, int dt_zone)
821{
822 struct mailimap_date_time * date_time;
823
824 date_time = malloc(sizeof(* date_time));
825 if (date_time == NULL)
826 return NULL;
827
828 date_time->dt_day = dt_day;
829 date_time->dt_month = dt_month;
830 date_time->dt_year = dt_year;
831 date_time->dt_hour = dt_hour;
832 date_time->dt_min = dt_min;
833 date_time->dt_day = dt_sec;
834 date_time->dt_zone = dt_zone;
835
836 return date_time;
837}
838
839void mailimap_date_time_free(struct mailimap_date_time * date_time)
840{
841 free(date_time);
842}
843
844
845
846struct mailimap_envelope *
847mailimap_envelope_new(char * env_date, char * env_subject,
848 struct mailimap_env_from * env_from,
849 struct mailimap_env_sender * env_sender,
850 struct mailimap_env_reply_to * env_reply_to,
851 struct mailimap_env_to * env_to,
852 struct mailimap_env_cc* env_cc,
853 struct mailimap_env_bcc * env_bcc,
854 char * env_in_reply_to, char * env_message_id)
855{
856 struct mailimap_envelope * env;
857
858 env = malloc(sizeof(* env));
859 if (env == NULL)
860 return NULL;
861
862 env->env_date = env_date;
863 env->env_subject = env_subject;
864 env->env_from = env_from;
865 env->env_sender = env_sender;
866 env->env_reply_to = env_reply_to;
867 env->env_to = env_to;
868 env->env_cc = env_cc;
869 env->env_bcc = env_bcc;
870 env->env_in_reply_to = env_in_reply_to;
871 env->env_message_id = env_message_id;
872
873 return env;
874}
875
876
877void mailimap_envelope_free(struct mailimap_envelope * env)
878{
879 if (env->env_date)
880 mailimap_env_date_free(env->env_date);
881 if (env->env_subject)
882 mailimap_env_subject_free(env->env_subject);
883 if (env->env_from)
884 mailimap_env_from_free(env->env_from);
885 if (env->env_sender)
886 mailimap_env_sender_free(env->env_sender);
887 if (env->env_reply_to)
888 mailimap_env_reply_to_free(env->env_reply_to);
889 if (env->env_to)
890 mailimap_env_to_free(env->env_to);
891 if (env->env_cc)
892 mailimap_env_cc_free(env->env_cc);
893 if (env->env_bcc)
894 mailimap_env_bcc_free(env->env_bcc);
895 if (env->env_in_reply_to)
896 mailimap_env_in_reply_to_free(env->env_in_reply_to);
897 if (env->env_message_id)
898 mailimap_env_message_id_free(env->env_message_id);
899
900 free(env);
901}
902
903
904static void mailimap_address_list_free(clist * addr_list)
905{
906 if (addr_list != NULL) {
907 clist_foreach(addr_list, (clist_func) mailimap_address_free, NULL);
908 clist_free(addr_list);
909 }
910}
911
912
913struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list)
914{
915 struct mailimap_env_bcc * env_bcc;
916
917 env_bcc = malloc(sizeof(* env_bcc));
918 if (env_bcc == NULL)
919 return NULL;
920 env_bcc->bcc_list = bcc_list;
921
922 return env_bcc;
923}
924
925void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc)
926{
927 mailimap_address_list_free(env_bcc->bcc_list);
928 free(env_bcc);
929}
930
931
932struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list)
933{
934 struct mailimap_env_cc * env_cc;
935
936 env_cc = malloc(sizeof(* env_cc));
937 if (env_cc == NULL)
938 return NULL;
939 env_cc->cc_list = cc_list;
940
941 return env_cc;
942}
943
944void mailimap_env_cc_free(struct mailimap_env_cc * env_cc)
945{
946 mailimap_address_list_free(env_cc->cc_list);
947 free(env_cc);
948}
949
950
951void mailimap_env_date_free(char * date)
952{
953 mailimap_nstring_free(date);
954}
955
956
957struct mailimap_env_from * mailimap_env_from_new(clist * frm_list)
958{
959 struct mailimap_env_from * env_from;
960
961 env_from = malloc(sizeof(* env_from));
962 if (env_from == NULL)
963 return NULL;
964 env_from->frm_list = frm_list;
965
966 return env_from;
967}
968
969void mailimap_env_from_free(struct mailimap_env_from * env_from)
970{
971 mailimap_address_list_free(env_from->frm_list);
972 free(env_from);
973}
974
975
976void mailimap_env_in_reply_to_free(char * in_reply_to)
977{
978 mailimap_nstring_free(in_reply_to);
979}
980
981void mailimap_env_message_id_free(char * message_id)
982{
983 mailimap_nstring_free(message_id);
984}
985
986struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list)
987{
988 struct mailimap_env_reply_to * env_reply_to;
989
990 env_reply_to = malloc(sizeof(* env_reply_to));
991 if (env_reply_to == NULL)
992 return NULL;
993 env_reply_to->rt_list = rt_list;
994
995 return env_reply_to;
996}
997
998void
999mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to)
1000{
1001 mailimap_address_list_free(env_reply_to->rt_list);
1002 free(env_reply_to);
1003}
1004
1005struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list)
1006{
1007 struct mailimap_env_sender * env_sender;
1008
1009 env_sender = malloc(sizeof(* env_sender));
1010 if (env_sender == NULL)
1011 return NULL;
1012 env_sender->snd_list = snd_list;
1013
1014 return env_sender;
1015}
1016
1017void mailimap_env_sender_free(struct mailimap_env_sender * env_sender)
1018{
1019 mailimap_address_list_free(env_sender->snd_list);
1020 free(env_sender);
1021}
1022
1023void mailimap_env_subject_free(char * subject)
1024{
1025 mailimap_nstring_free(subject);
1026}
1027
1028struct mailimap_env_to * mailimap_env_to_new(clist * to_list)
1029{
1030 struct mailimap_env_to * env_to;
1031
1032 env_to = malloc(sizeof(* env_to));
1033 if (env_to == NULL)
1034 return NULL;
1035 env_to->to_list = to_list;
1036
1037 return env_to;
1038}
1039
1040void mailimap_env_to_free(struct mailimap_env_to * env_to)
1041{
1042 mailimap_address_list_free(env_to->to_list);
1043 free(env_to);
1044}
1045
1046
1047
1048struct mailimap_flag * mailimap_flag_new(int fl_type,
1049 char * fl_keyword, char * fl_extension)
1050{
1051 struct mailimap_flag * f;
1052
1053 f = malloc(sizeof(* f));
1054 if (f == NULL)
1055 return NULL;
1056 f->fl_type = fl_type;
1057 switch (fl_type) {
1058 case MAILIMAP_FLAG_KEYWORD:
1059 f->fl_data.fl_keyword = fl_keyword;
1060 break;
1061 case MAILIMAP_FLAG_EXTENSION:
1062 f->fl_data.fl_extension = fl_extension;
1063 break;
1064 }
1065
1066 return f;
1067}
1068
1069void mailimap_flag_free(struct mailimap_flag * f)
1070{
1071 switch (f->fl_type) {
1072 case MAILIMAP_FLAG_KEYWORD:
1073 mailimap_flag_keyword_free(f->fl_data.fl_keyword);
1074 break;
1075 case MAILIMAP_FLAG_EXTENSION:
1076 mailimap_flag_extension_free(f->fl_data.fl_extension);
1077 break;
1078 }
1079 free(f);
1080}
1081
1082
1083
1084void mailimap_flag_extension_free(char * flag_extension)
1085{
1086 mailimap_atom_free(flag_extension);
1087}
1088
1089
1090
1091struct mailimap_flag_fetch *
1092mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag)
1093{
1094 struct mailimap_flag_fetch * flag_fetch;
1095
1096 flag_fetch = malloc(sizeof(* flag_fetch));
1097 if (flag_fetch == NULL)
1098 return NULL;
1099
1100 flag_fetch->fl_type = fl_type;
1101 flag_fetch->fl_flag = fl_flag;
1102
1103 return flag_fetch;
1104}
1105
1106void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch)
1107{
1108 if (flag_fetch->fl_flag)
1109 mailimap_flag_free(flag_fetch->fl_flag);
1110 free(flag_fetch);
1111}
1112
1113
1114
1115void mailimap_flag_keyword_free(char * flag_keyword)
1116{
1117 mailimap_atom_free(flag_keyword);
1118}
1119
1120
1121
1122
1123struct mailimap_flag_list *
1124mailimap_flag_list_new(clist * fl_list)
1125{
1126 struct mailimap_flag_list * flag_list;
1127
1128 flag_list = malloc(sizeof(* flag_list));
1129 if (flag_list == NULL)
1130 return NULL;
1131 flag_list->fl_list = fl_list;
1132
1133 return flag_list;
1134}
1135
1136void mailimap_flag_list_free(struct mailimap_flag_list * flag_list)
1137{
1138 clist_foreach(flag_list->fl_list, (clist_func) mailimap_flag_free, NULL);
1139 clist_free(flag_list->fl_list);
1140 free(flag_list);
1141}
1142
1143
1144
1145
1146
1147struct mailimap_flag_perm *
1148mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag)
1149{
1150 struct mailimap_flag_perm * flag_perm;
1151
1152 flag_perm = malloc(sizeof(* flag_perm));
1153 if (flag_perm == NULL)
1154 return NULL;
1155
1156 flag_perm->fl_type = fl_type;
1157 flag_perm->fl_flag = fl_flag;
1158
1159 return flag_perm;
1160}
1161
1162void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm)
1163{
1164 if (flag_perm->fl_flag != NULL)
1165 mailimap_flag_free(flag_perm->fl_flag);
1166 free(flag_perm);
1167}
1168
1169
1170
1171
1172struct mailimap_greeting *
1173mailimap_greeting_new(int gr_type,
1174 struct mailimap_resp_cond_auth * gr_auth,
1175 struct mailimap_resp_cond_bye * gr_bye)
1176{
1177 struct mailimap_greeting * greeting;
1178
1179 greeting = malloc(sizeof(* greeting));
1180 if (greeting == NULL)
1181 return NULL;
1182 greeting->gr_type = gr_type;
1183 switch (gr_type) {
1184 case MAILIMAP_GREETING_RESP_COND_AUTH:
1185 greeting->gr_data.gr_auth = gr_auth;
1186 break;
1187 case MAILIMAP_GREETING_RESP_COND_BYE:
1188 greeting->gr_data.gr_bye = gr_bye;
1189 break;
1190 }
1191
1192 return greeting;
1193}
1194
1195void mailimap_greeting_free(struct mailimap_greeting * greeting)
1196{
1197 switch (greeting->gr_type) {
1198 case MAILIMAP_GREETING_RESP_COND_AUTH:
1199 mailimap_resp_cond_auth_free(greeting->gr_data.gr_auth);
1200 break;
1201 case MAILIMAP_GREETING_RESP_COND_BYE:
1202 mailimap_resp_cond_bye_free(greeting->gr_data.gr_bye);
1203 break;
1204 }
1205 free(greeting);
1206}
1207
1208
1209
1210void
1211mailimap_header_fld_name_free(char * header_fld_name)
1212{
1213 mailimap_astring_free(header_fld_name);
1214}
1215
1216
1217
1218struct mailimap_header_list *
1219mailimap_header_list_new(clist * hdr_list)
1220{
1221 struct mailimap_header_list * header_list;
1222
1223 header_list = malloc(sizeof(* header_list));
1224 if (header_list == NULL)
1225 return NULL;
1226
1227 header_list->hdr_list = hdr_list;
1228
1229 return header_list;
1230}
1231
1232void
1233mailimap_header_list_free(struct mailimap_header_list * header_list)
1234{
1235 clist_foreach(header_list->hdr_list,
1236 (clist_func) mailimap_header_fld_name_free,
1237 NULL);
1238 clist_free(header_list->hdr_list);
1239 free(header_list);
1240}
1241
1242
1243
1244void mailimap_literal_free(char * literal)
1245{
1246 /* free(literal); */
1247 mmap_string_unref(literal);
1248}
1249
1250void mailimap_mailbox_free(char * mb)
1251{
1252 mailimap_astring_free(mb);
1253}
1254
1255
1256
1257
1258struct mailimap_status_info *
1259mailimap_status_info_new(int st_att, uint32_t st_value)
1260{
1261 struct mailimap_status_info * info;
1262
1263 info = malloc(sizeof(* info));
1264 if (info == NULL)
1265 return NULL;
1266 info->st_att = st_att;
1267 info->st_value = st_value;
1268
1269 return info;
1270}
1271
1272void mailimap_status_info_free(struct mailimap_status_info * info)
1273{
1274 free(info);
1275}
1276
1277
1278
1279struct mailimap_mailbox_data_status *
1280mailimap_mailbox_data_status_new(char * st_mailbox,
1281 clist * st_info_list)
1282{
1283 struct mailimap_mailbox_data_status * mb_data_status;
1284
1285 mb_data_status = malloc(sizeof(* mb_data_status));
1286 if (mb_data_status == NULL)
1287 return NULL;
1288 mb_data_status->st_mailbox = st_mailbox;
1289 mb_data_status->st_info_list = st_info_list;
1290
1291 return mb_data_status;
1292}
1293
1294void
1295mailimap_mailbox_data_search_free(clist * data_search)
1296{
1297 clist_foreach(data_search, (clist_func) mailimap_number_alloc_free, NULL);
1298 clist_free(data_search);
1299}
1300
1301void
1302mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info)
1303{
1304 mailimap_mailbox_free(info->st_mailbox);
1305 clist_foreach(info->st_info_list, (clist_func) mailimap_status_info_free,
1306 NULL);
1307 clist_free(info->st_info_list);
1308 free(info);
1309}
1310
1311
1312static void
1313mailimap_mailbox_data_flags_free(struct mailimap_flag_list * flag_list)
1314{
1315 mailimap_flag_list_free(flag_list);
1316}
1317
1318static void
1319mailimap_mailbox_data_list_free(struct mailimap_mailbox_list * mb_list)
1320{
1321 mailimap_mailbox_list_free(mb_list);
1322}
1323
1324static void
1325mailimap_mailbox_data_lsub_free(struct mailimap_mailbox_list * mb_lsub)
1326{
1327 mailimap_mailbox_list_free(mb_lsub);
1328}
1329
1330
1331
1332
1333
1334
1335struct mailimap_mailbox_data *
1336mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags,
1337 struct mailimap_mailbox_list * mbd_list,
1338 struct mailimap_mailbox_list * mbd_lsub,
1339 clist * mbd_search,
1340 struct mailimap_mailbox_data_status * mbd_status,
1341 uint32_t mbd_exists,
1342 uint32_t mbd_recent)
1343{
1344 struct mailimap_mailbox_data * data;
1345
1346 data = malloc(sizeof(* data));
1347 if (data == NULL)
1348 return NULL;
1349
1350 data->mbd_type = mbd_type;
1351 switch (mbd_type) {
1352 case MAILIMAP_MAILBOX_DATA_FLAGS:
1353 data->mbd_data.mbd_flags = mbd_flags;
1354 break;
1355 case MAILIMAP_MAILBOX_DATA_LIST:
1356 data->mbd_data.mbd_list = mbd_list;
1357 break;
1358 case MAILIMAP_MAILBOX_DATA_LSUB:
1359 data->mbd_data.mbd_lsub = mbd_lsub;
1360 break;
1361 case MAILIMAP_MAILBOX_DATA_SEARCH:
1362 data->mbd_data.mbd_search = mbd_search;
1363 break;
1364 case MAILIMAP_MAILBOX_DATA_STATUS:
1365 data->mbd_data.mbd_status = mbd_status;
1366 break;
1367 case MAILIMAP_MAILBOX_DATA_EXISTS:
1368 data->mbd_data.mbd_exists = mbd_exists;
1369 break;
1370 case MAILIMAP_MAILBOX_DATA_RECENT:
1371 data->mbd_data.mbd_recent = mbd_recent;
1372 break;
1373 }
1374
1375 return data;
1376}
1377
1378void
1379mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data)
1380{
1381 switch (mb_data->mbd_type) {
1382 case MAILIMAP_MAILBOX_DATA_FLAGS:
1383 if (mb_data->mbd_data.mbd_flags != NULL)
1384 mailimap_mailbox_data_flags_free(mb_data->mbd_data.mbd_flags);
1385 break;
1386 case MAILIMAP_MAILBOX_DATA_LIST:
1387 if (mb_data->mbd_data.mbd_list != NULL)
1388 mailimap_mailbox_data_list_free(mb_data->mbd_data.mbd_list);
1389 break;
1390 case MAILIMAP_MAILBOX_DATA_LSUB:
1391 if (mb_data->mbd_data.mbd_lsub != NULL)
1392 mailimap_mailbox_data_lsub_free(mb_data->mbd_data.mbd_lsub);
1393 break;
1394 case MAILIMAP_MAILBOX_DATA_SEARCH:
1395 if (mb_data->mbd_data.mbd_search != NULL)
1396 mailimap_mailbox_data_search_free(mb_data->mbd_data.mbd_search);
1397 break;
1398 case MAILIMAP_MAILBOX_DATA_STATUS:
1399 if (mb_data->mbd_data.mbd_status != NULL)
1400 mailimap_mailbox_data_status_free(mb_data->mbd_data.mbd_status);
1401 break;
1402 }
1403 free(mb_data);
1404}
1405
1406
1407
1408
1409
1410struct mailimap_mbx_list_flags *
1411mailimap_mbx_list_flags_new(int mbf_type, clist * mbf_oflags,
1412 int mbf_sflag)
1413{
1414 struct mailimap_mbx_list_flags * mbx_list_flags;
1415
1416 mbx_list_flags = malloc(sizeof(* mbx_list_flags));
1417 if (mbx_list_flags == NULL)
1418 return NULL;
1419
1420 mbx_list_flags->mbf_type = mbf_type;
1421 mbx_list_flags->mbf_oflags = mbf_oflags;
1422 mbx_list_flags->mbf_sflag = mbf_sflag;
1423
1424 return mbx_list_flags;
1425}
1426
1427void
1428mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags)
1429{
1430 clist_foreach(mbx_list_flags->mbf_oflags,
1431 (clist_func) mailimap_mbx_list_oflag_free,
1432 NULL);
1433 clist_free(mbx_list_flags->mbf_oflags);
1434
1435 free(mbx_list_flags);
1436}
1437
1438
1439struct mailimap_mbx_list_oflag *
1440mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext)
1441{
1442 struct mailimap_mbx_list_oflag * oflag;
1443
1444 oflag = malloc(sizeof(* oflag));
1445 if (oflag == NULL)
1446 return NULL;
1447
1448 oflag->of_type = of_type;
1449 oflag->of_flag_ext = of_flag_ext;
1450
1451 return oflag;
1452}
1453
1454void
1455mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag)
1456{
1457 if (oflag->of_flag_ext != NULL)
1458 mailimap_flag_extension_free(oflag->of_flag_ext);
1459 free(oflag);
1460}
1461
1462
1463
1464struct mailimap_mailbox_list *
1465mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags,
1466 char mb_delimiter, char * mb_name)
1467{
1468 struct mailimap_mailbox_list * mb_list;
1469
1470 mb_list = malloc(sizeof(* mb_list));
1471 if (mb_list == NULL)
1472 return NULL;
1473
1474 mb_list->mb_flag = mbx_flags;
1475 mb_list->mb_delimiter = mb_delimiter;
1476 mb_list->mb_name = mb_name;
1477
1478 return mb_list;
1479}
1480
1481void
1482mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list)
1483{
1484 if (mb_list->mb_flag != NULL)
1485 mailimap_mbx_list_flags_free(mb_list->mb_flag);
1486 if (mb_list->mb_name != NULL)
1487 mailimap_mailbox_free(mb_list->mb_name);
1488 free(mb_list);
1489}
1490
1491
1492
1493struct mailimap_media_basic *
1494mailimap_media_basic_new(int med_type,
1495 char * med_basic_type, char * med_subtype)
1496{
1497 struct mailimap_media_basic * media_basic;
1498
1499 media_basic = malloc(sizeof(* media_basic));
1500 if (media_basic == NULL)
1501 return NULL;
1502 media_basic->med_type = med_type;
1503 media_basic->med_basic_type = med_basic_type;
1504 media_basic->med_subtype = med_subtype;
1505
1506 return media_basic;
1507}
1508
1509void
1510mailimap_media_basic_free(struct mailimap_media_basic * media_basic)
1511{
1512 mailimap_string_free(media_basic->med_basic_type);
1513 mailimap_media_subtype_free(media_basic->med_subtype);
1514 free(media_basic);
1515}
1516
1517
1518
1519void mailimap_media_subtype_free(char * media_subtype)
1520{
1521 mmap_string_unref(media_subtype);
1522}
1523
1524
1525void mailimap_media_text_free(char * media_text)
1526{
1527 mailimap_media_subtype_free(media_text);
1528}
1529
1530
1531
1532struct mailimap_message_data *
1533mailimap_message_data_new(uint32_t mdt_number, int mdt_type,
1534 struct mailimap_msg_att * mdt_msg_att)
1535{
1536 struct mailimap_message_data * msg_data;
1537
1538 msg_data = malloc(sizeof(* msg_data));
1539 if (msg_data == NULL)
1540 free(msg_data);
1541
1542 msg_data->mdt_number = mdt_number;
1543 msg_data->mdt_type = mdt_type;
1544 msg_data->mdt_msg_att = mdt_msg_att;
1545
1546 return msg_data;
1547}
1548
1549void
1550mailimap_message_data_free(struct mailimap_message_data * msg_data)
1551{
1552 if (msg_data->mdt_msg_att != NULL)
1553 mailimap_msg_att_free(msg_data->mdt_msg_att);
1554 free(msg_data);
1555}
1556
1557
1558
1559
1560struct mailimap_msg_att_item *
1561mailimap_msg_att_item_new(int att_type,
1562 struct mailimap_msg_att_dynamic * att_dyn,
1563 struct mailimap_msg_att_static * att_static)
1564{
1565 struct mailimap_msg_att_item * item;
1566
1567 item = malloc(sizeof(* item));
1568 if (item == NULL)
1569 return item;
1570
1571 item->att_type = att_type;
1572 switch (att_type) {
1573 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
1574 item->att_data.att_dyn = att_dyn;
1575 break;
1576 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1577 item->att_data.att_static = att_static;
1578 break;
1579 }
1580
1581 return item;
1582}
1583
1584void
1585mailimap_msg_att_item_free(struct mailimap_msg_att_item * item)
1586{
1587 switch (item->att_type) {
1588 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
1589 mailimap_msg_att_dynamic_free(item->att_data.att_dyn);
1590 break;
1591 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1592 mailimap_msg_att_static_free(item->att_data.att_static);
1593 break;
1594 }
1595 free(item);
1596}
1597
1598
1599struct mailimap_msg_att *
1600mailimap_msg_att_new(clist * att_list)
1601{
1602 struct mailimap_msg_att * msg_att;
1603
1604 msg_att = malloc(sizeof(* msg_att));
1605 if (msg_att == NULL)
1606 return NULL;
1607
1608 msg_att->att_list = att_list;
1609 msg_att->att_number = 0;
1610
1611 return msg_att;
1612}
1613
1614void mailimap_msg_att_free(struct mailimap_msg_att * msg_att)
1615{
1616 clist_foreach(msg_att->att_list,
1617 (clist_func) mailimap_msg_att_item_free, NULL);
1618 clist_free(msg_att->att_list);
1619 free(msg_att);
1620}
1621
1622
1623
1624struct mailimap_msg_att_dynamic *
1625mailimap_msg_att_dynamic_new(clist * att_list)
1626{
1627 struct mailimap_msg_att_dynamic * msg_att_dyn;
1628
1629 msg_att_dyn = malloc(sizeof(* msg_att_dyn));
1630 if (msg_att_dyn == NULL)
1631 return NULL;
1632
1633 msg_att_dyn->att_list = att_list;
1634
1635 return msg_att_dyn;
1636}
1637
1638void
1639mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn)
1640{
1641 if (msg_att_dyn->att_list != NULL) {
1642 clist_foreach(msg_att_dyn->att_list,
1643 (clist_func) mailimap_flag_fetch_free,
1644 NULL);
1645 clist_free(msg_att_dyn->att_list);
1646 }
1647 free(msg_att_dyn);
1648}
1649
1650
1651struct mailimap_msg_att_body_section *
1652mailimap_msg_att_body_section_new(struct mailimap_section * sec_section,
1653 uint32_t sec_origin_octet,
1654 char * sec_body_part,
1655 size_t sec_length)
1656{
1657 struct mailimap_msg_att_body_section * msg_att_body_section;
1658
1659 msg_att_body_section = malloc(sizeof(* msg_att_body_section));
1660 if (msg_att_body_section == NULL)
1661 return NULL;
1662
1663 msg_att_body_section->sec_section = sec_section;
1664 msg_att_body_section->sec_origin_octet = sec_origin_octet;
1665 msg_att_body_section->sec_body_part = sec_body_part;
1666 msg_att_body_section->sec_length = sec_length;
1667
1668 return msg_att_body_section;
1669}
1670
1671void
1672mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section *
1673 msg_att_body_section)
1674{
1675 if (msg_att_body_section->sec_section != NULL)
1676 mailimap_section_free(msg_att_body_section->sec_section);
1677 if (msg_att_body_section->sec_body_part != NULL)
1678 mailimap_nstring_free(msg_att_body_section->sec_body_part);
1679 free(msg_att_body_section);
1680}
1681
1682
1683
1684
1685
1686
1687void mailimap_msg_att_envelope_free(struct mailimap_envelope * env)
1688{
1689 mailimap_envelope_free(env);
1690}
1691
1692void
1693mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time)
1694{
1695 mailimap_date_time_free(date_time);
1696}
1697
1698void
1699mailimap_msg_att_rfc822_free(char * str)
1700{
1701 mailimap_nstring_free(str);
1702}
1703
1704
1705void
1706mailimap_msg_att_rfc822_header_free(char * str)
1707{
1708 mailimap_nstring_free(str);
1709}
1710
1711void
1712mailimap_msg_att_rfc822_text_free(char * str)
1713{
1714 mailimap_nstring_free(str);
1715}
1716
1717void
1718mailimap_msg_att_body_free(struct mailimap_body * body)
1719{
1720 mailimap_body_free(body);
1721}
1722
1723void
1724mailimap_msg_att_bodystructure_free(struct mailimap_body * body)
1725{
1726 mailimap_body_free(body);
1727}
1728
1729
1730
1731struct mailimap_msg_att_static *
1732mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env,
1733 struct mailimap_date_time * att_internal_date,
1734 char * att_rfc822,
1735 char * att_rfc822_header,
1736 char * att_rfc822_text,
1737 size_t att_length,
1738 uint32_t att_rfc822_size,
1739 struct mailimap_body * att_bodystructure,
1740 struct mailimap_body * att_body,
1741 struct mailimap_msg_att_body_section * att_body_section,
1742 uint32_t att_uid)
1743{
1744 struct mailimap_msg_att_static * item;
1745
1746 item = malloc(sizeof(* item));
1747 if (item == NULL)
1748 return FALSE;
1749
1750 item->att_type = att_type;
1751 switch (att_type) {
1752 case MAILIMAP_MSG_ATT_ENVELOPE:
1753 item->att_data.att_env = att_env;
1754 break;
1755 case MAILIMAP_MSG_ATT_INTERNALDATE:
1756 item->att_data.att_internal_date = att_internal_date;
1757 break;
1758 case MAILIMAP_MSG_ATT_RFC822:
1759 item->att_data.att_rfc822.att_content = att_rfc822;
1760 item->att_data.att_rfc822.att_length = att_length;
1761 break;
1762 case MAILIMAP_MSG_ATT_RFC822_HEADER:
1763 item->att_data.att_rfc822_header.att_content = att_rfc822_header;
1764 item->att_data.att_rfc822_header.att_length = att_length;
1765 break;
1766 case MAILIMAP_MSG_ATT_RFC822_TEXT:
1767 item->att_data.att_rfc822_text.att_content = att_rfc822_text;
1768 item->att_data.att_rfc822_text.att_length = att_length;
1769 break;
1770 case MAILIMAP_MSG_ATT_RFC822_SIZE:
1771 item->att_data.att_rfc822_size = att_rfc822_size;
1772 break;
1773 case MAILIMAP_MSG_ATT_BODY:
1774 item->att_data.att_body = att_body;
1775 break;
1776 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
1777 item->att_data.att_bodystructure = att_bodystructure;
1778 break;
1779 case MAILIMAP_MSG_ATT_BODY_SECTION:
1780 item->att_data.att_body_section = att_body_section;
1781 break;
1782 case MAILIMAP_MSG_ATT_UID:
1783 item->att_data.att_uid = att_uid;
1784 break;
1785 }
1786
1787 return item;
1788}
1789
1790void
1791mailimap_msg_att_static_free(struct mailimap_msg_att_static * item)
1792{
1793 switch (item->att_type) {
1794 case MAILIMAP_MSG_ATT_ENVELOPE:
1795 if (item->att_data.att_env != NULL)
1796 mailimap_msg_att_envelope_free(item->att_data.att_env);
1797 break;
1798 case MAILIMAP_MSG_ATT_INTERNALDATE:
1799 if (item->att_data.att_internal_date != NULL)
1800 mailimap_msg_att_internaldate_free(item->att_data.att_internal_date);
1801 break;
1802 case MAILIMAP_MSG_ATT_RFC822:
1803 if (item->att_data.att_rfc822.att_content != NULL)
1804 mailimap_msg_att_rfc822_free(item->att_data.att_rfc822.att_content);
1805 break;
1806 case MAILIMAP_MSG_ATT_RFC822_HEADER:
1807 if (item->att_data.att_rfc822_header.att_content != NULL)
1808 mailimap_msg_att_rfc822_header_free(item->att_data.att_rfc822_header.att_content);
1809 break;
1810 case MAILIMAP_MSG_ATT_RFC822_TEXT:
1811 if (item->att_data.att_rfc822_text.att_content != NULL)
1812 mailimap_msg_att_rfc822_text_free(item->att_data.att_rfc822_text.att_content);
1813 break;
1814 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
1815 if (item->att_data.att_bodystructure != NULL)
1816 mailimap_msg_att_bodystructure_free(item->att_data.att_bodystructure);
1817 break;
1818 case MAILIMAP_MSG_ATT_BODY:
1819 if (item->att_data.att_body != NULL)
1820 mailimap_msg_att_body_free(item->att_data.att_body);
1821 break;
1822 case MAILIMAP_MSG_ATT_BODY_SECTION:
1823 if (item->att_data.att_body_section != NULL)
1824 mailimap_msg_att_body_section_free(item->att_data.att_body_section);
1825 break;
1826 }
1827 free(item);
1828}
1829
1830
1831
1832
1833void mailimap_nstring_free(char * str)
1834{
1835 if (str != NULL)
1836 mailimap_string_free(str);
1837}
1838
1839
1840
1841
1842
1843
1844
1845struct mailimap_cont_req_or_resp_data *
1846mailimap_cont_req_or_resp_data_new(int rsp_type,
1847 struct mailimap_continue_req * rsp_cont_req,
1848 struct mailimap_response_data * rsp_resp_data)
1849{
1850 struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data;
1851
1852 cont_req_or_resp_data = malloc(sizeof(* cont_req_or_resp_data));
1853 if (cont_req_or_resp_data == NULL)
1854 return NULL;
1855
1856 cont_req_or_resp_data->rsp_type = rsp_type;
1857 switch (rsp_type) {
1858 case MAILIMAP_RESP_CONT_REQ:
1859 cont_req_or_resp_data->rsp_data.rsp_cont_req = rsp_cont_req;
1860 break;
1861 case MAILIMAP_RESP_RESP_DATA:
1862 cont_req_or_resp_data->rsp_data.rsp_resp_data = rsp_resp_data;
1863 break;
1864 }
1865
1866 return cont_req_or_resp_data;
1867}
1868
1869void
1870mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data *
1871 cont_req_or_resp_data)
1872{
1873 switch (cont_req_or_resp_data->rsp_type) {
1874 case MAILIMAP_RESP_CONT_REQ:
1875 if (cont_req_or_resp_data->rsp_data.rsp_cont_req != NULL)
1876 mailimap_continue_req_free(cont_req_or_resp_data->rsp_data.rsp_cont_req);
1877 break;
1878 case MAILIMAP_RESP_RESP_DATA:
1879 if (cont_req_or_resp_data->rsp_data.rsp_resp_data != NULL)
1880 mailimap_response_data_free(cont_req_or_resp_data->rsp_data.rsp_resp_data);
1881 break;
1882 }
1883 free(cont_req_or_resp_data);
1884}
1885
1886
1887
1888
1889struct mailimap_response *
1890mailimap_response_new(clist * rsp_cont_req_or_resp_data_list,
1891 struct mailimap_response_done * rsp_resp_done)
1892{
1893 struct mailimap_response * resp;
1894
1895 resp = malloc(sizeof(* resp));
1896 if (resp == NULL)
1897 return NULL;
1898
1899 resp->rsp_cont_req_or_resp_data_list = rsp_cont_req_or_resp_data_list;
1900 resp->rsp_resp_done = rsp_resp_done;
1901
1902 return resp;
1903}
1904
1905void
1906mailimap_response_free(struct mailimap_response * resp)
1907{
1908 if (resp->rsp_cont_req_or_resp_data_list != NULL) {
1909 clist_foreach(resp->rsp_cont_req_or_resp_data_list,
1910 (clist_func) mailimap_cont_req_or_resp_data_free, NULL);
1911 clist_free(resp->rsp_cont_req_or_resp_data_list);
1912 }
1913 mailimap_response_done_free(resp->rsp_resp_done);
1914 free(resp);
1915}
1916
1917
1918
1919struct mailimap_response_data *
1920mailimap_response_data_new(int rsp_type,
1921 struct mailimap_resp_cond_state * rsp_cond_state,
1922 struct mailimap_resp_cond_bye * rsp_bye,
1923 struct mailimap_mailbox_data * rsp_mailbox_data,
1924 struct mailimap_message_data * rsp_message_data,
1925 struct mailimap_capability_data * rsp_capability_data)
1926{
1927 struct mailimap_response_data * resp_data;
1928
1929 resp_data = malloc(sizeof(* resp_data));
1930 if (resp_data == NULL)
1931 return NULL;
1932 resp_data->rsp_type = rsp_type;
1933
1934 switch (rsp_type) {
1935 case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
1936 resp_data->rsp_data.rsp_cond_state = rsp_cond_state;
1937 break;
1938 case MAILIMAP_RESP_DATA_TYPE_COND_BYE:
1939 resp_data->rsp_data.rsp_bye = rsp_bye;
1940 break;
1941 case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
1942 resp_data->rsp_data.rsp_mailbox_data = rsp_mailbox_data;
1943 break;
1944 case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
1945 resp_data->rsp_data.rsp_message_data = rsp_message_data;
1946 break;
1947 case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
1948 resp_data->rsp_data.rsp_capability_data = rsp_capability_data;
1949 break;
1950 }
1951
1952 return resp_data;
1953}
1954
1955void
1956mailimap_response_data_free(struct mailimap_response_data * resp_data)
1957{
1958 switch (resp_data->rsp_type) {
1959 case MAILIMAP_RESP_DATA_TYPE_COND_STATE:
1960 if (resp_data->rsp_data.rsp_cond_state != NULL)
1961 mailimap_resp_cond_state_free(resp_data->rsp_data.rsp_cond_state);
1962 break;
1963 case MAILIMAP_RESP_DATA_TYPE_COND_BYE:
1964 if (resp_data->rsp_data.rsp_bye != NULL)
1965 mailimap_resp_cond_bye_free(resp_data->rsp_data.rsp_bye);
1966 break;
1967 case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA:
1968 if (resp_data->rsp_data.rsp_mailbox_data != NULL)
1969 mailimap_mailbox_data_free(resp_data->rsp_data.rsp_mailbox_data);
1970 break;
1971 case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA:
1972 if (resp_data->rsp_data.rsp_message_data != NULL)
1973 mailimap_message_data_free(resp_data->rsp_data.rsp_message_data);
1974 break;
1975 case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA:
1976 if (resp_data->rsp_data.rsp_capability_data != NULL)
1977 mailimap_capability_data_free(resp_data->rsp_data.rsp_capability_data);
1978 break;
1979 }
1980 free(resp_data);
1981}
1982
1983
1984
1985struct mailimap_response_done *
1986mailimap_response_done_new(int rsp_type,
1987 struct mailimap_response_tagged * rsp_tagged,
1988 struct mailimap_response_fatal * rsp_fatal)
1989{
1990 struct mailimap_response_done * resp_done;
1991
1992 resp_done = malloc(sizeof(* resp_done));
1993 if (resp_done == NULL)
1994 return NULL;
1995
1996 resp_done->rsp_type = rsp_type;
1997 switch (rsp_type) {
1998 case MAILIMAP_RESP_DONE_TYPE_TAGGED:
1999 resp_done->rsp_data.rsp_tagged = rsp_tagged;
2000 break;
2001 case MAILIMAP_RESP_DONE_TYPE_FATAL:
2002 resp_done->rsp_data.rsp_fatal = rsp_fatal;
2003 break;
2004 }
2005
2006 return resp_done;
2007}
2008
2009void mailimap_response_done_free(struct mailimap_response_done *
2010 resp_done)
2011{
2012 switch (resp_done->rsp_type) {
2013 case MAILIMAP_RESP_DONE_TYPE_TAGGED:
2014 mailimap_response_tagged_free(resp_done->rsp_data.rsp_tagged);
2015 break;
2016 case MAILIMAP_RESP_DONE_TYPE_FATAL:
2017 mailimap_response_fatal_free(resp_done->rsp_data.rsp_fatal);
2018 break;
2019 }
2020 free(resp_done);
2021}
2022
2023struct mailimap_response_fatal *
2024mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye)
2025{
2026 struct mailimap_response_fatal * resp_fatal;
2027
2028 resp_fatal = malloc(sizeof(* resp_fatal));
2029 if (resp_fatal == NULL)
2030 return NULL;
2031
2032 resp_fatal->rsp_bye = rsp_bye;
2033
2034 return NULL;
2035}
2036
2037void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal)
2038{
2039 mailimap_resp_cond_bye_free(resp_fatal->rsp_bye);
2040 free(resp_fatal);
2041}
2042
2043struct mailimap_response_tagged *
2044mailimap_response_tagged_new(char * rsp_tag,
2045 struct mailimap_resp_cond_state * rsp_cond_state)
2046{
2047 struct mailimap_response_tagged * resp_tagged;
2048
2049 resp_tagged = malloc(sizeof(* resp_tagged));
2050 if (resp_tagged == NULL)
2051 return NULL;
2052
2053 resp_tagged->rsp_tag = rsp_tag;
2054 resp_tagged->rsp_cond_state = rsp_cond_state;
2055
2056 return resp_tagged;
2057}
2058
2059void
2060mailimap_response_tagged_free(struct mailimap_response_tagged * tagged)
2061{
2062 mailimap_tag_free(tagged->rsp_tag);
2063 mailimap_resp_cond_state_free(tagged->rsp_cond_state);
2064 free(tagged);
2065}
2066
2067
2068
2069struct mailimap_resp_cond_auth *
2070mailimap_resp_cond_auth_new(int rsp_type,
2071 struct mailimap_resp_text * rsp_text)
2072{
2073 struct mailimap_resp_cond_auth * cond_auth;
2074
2075 cond_auth = malloc(sizeof(* cond_auth));
2076 if (cond_auth == NULL)
2077 return NULL;
2078
2079 cond_auth->rsp_type = rsp_type;
2080 cond_auth->rsp_text = rsp_text;
2081
2082 return cond_auth;
2083}
2084
2085void
2086mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth)
2087{
2088 mailimap_resp_text_free(cond_auth->rsp_text);
2089 free(cond_auth);
2090}
2091
2092
2093
2094struct mailimap_resp_cond_bye *
2095mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text)
2096{
2097 struct mailimap_resp_cond_bye * cond_bye;
2098
2099 cond_bye = malloc(sizeof(* cond_bye));
2100 if (cond_bye == NULL)
2101 return NULL;
2102
2103 cond_bye->rsp_text = rsp_text;
2104
2105 return cond_bye;
2106}
2107
2108
2109void
2110mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye)
2111{
2112 mailimap_resp_text_free(cond_bye->rsp_text);
2113 free(cond_bye);
2114}
2115
2116
2117struct mailimap_resp_cond_state *
2118mailimap_resp_cond_state_new(int rsp_type,
2119 struct mailimap_resp_text * rsp_text)
2120{
2121 struct mailimap_resp_cond_state * cond_state;
2122
2123 cond_state = malloc(sizeof(* cond_state));
2124 if (cond_state == NULL)
2125 return NULL;
2126
2127 cond_state->rsp_type = rsp_type;
2128 cond_state->rsp_text = rsp_text;
2129
2130 return cond_state;
2131}
2132
2133void
2134mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state)
2135{
2136 mailimap_resp_text_free(cond_state->rsp_text);
2137 free(cond_state);
2138}
2139
2140
2141struct mailimap_resp_text *
2142mailimap_resp_text_new(struct mailimap_resp_text_code * rsp_code,
2143 char * rsp_text)
2144{
2145 struct mailimap_resp_text * resp_text;
2146
2147 resp_text = malloc(sizeof(* resp_text));
2148 if (resp_text == NULL)
2149 return NULL;
2150
2151 resp_text->rsp_code = rsp_code;
2152 resp_text->rsp_text = rsp_text;
2153
2154 return resp_text;
2155}
2156
2157void mailimap_resp_text_free(struct mailimap_resp_text * resp_text)
2158{
2159 if (resp_text->rsp_code)
2160 mailimap_resp_text_code_free(resp_text->rsp_code);
2161 if (resp_text->rsp_text)
2162 mailimap_text_free(resp_text->rsp_text);
2163 free(resp_text);
2164}
2165
2166
2167
2168
2169struct mailimap_resp_text_code *
2170mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset,
2171 struct mailimap_capability_data * rc_cap_data,
2172 clist * rc_perm_flags,
2173 uint32_t rc_uidnext, uint32_t rc_uidvalidity,
2174 uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value)
2175{
2176 struct mailimap_resp_text_code * resp_text_code;
2177
2178 resp_text_code = malloc(sizeof(* resp_text_code));
2179 if (resp_text_code == NULL)
2180 return NULL;
2181
2182 resp_text_code->rc_type = rc_type;
2183 switch (rc_type) {
2184 case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
2185 resp_text_code->rc_data.rc_badcharset = rc_badcharset;
2186 break;
2187 case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
2188 resp_text_code->rc_data.rc_cap_data = rc_cap_data;
2189 break;
2190 case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
2191 resp_text_code->rc_data.rc_perm_flags = rc_perm_flags;
2192 break;
2193 case MAILIMAP_RESP_TEXT_CODE_UIDNEXT:
2194 resp_text_code->rc_data.rc_uidnext = rc_uidnext;
2195 break;
2196 case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY:
2197 resp_text_code->rc_data.rc_uidvalidity = rc_uidvalidity;
2198 break;
2199 case MAILIMAP_RESP_TEXT_CODE_UNSEEN:
2200 resp_text_code->rc_data.rc_first_unseen = rc_first_unseen;
2201 break;
2202 case MAILIMAP_RESP_TEXT_CODE_OTHER:
2203 resp_text_code->rc_data.rc_atom.atom_name = rc_atom;
2204 resp_text_code->rc_data.rc_atom.atom_value = rc_atom_value;
2205 break;
2206 }
2207
2208 return resp_text_code;
2209}
2210
2211void
2212mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code)
2213{
2214 switch (resp_text_code->rc_type) {
2215 case MAILIMAP_RESP_TEXT_CODE_BADCHARSET:
2216 if (resp_text_code->rc_data.rc_badcharset != NULL) {
2217 clist_foreach(resp_text_code->rc_data.rc_badcharset,
2218 (clist_func) mailimap_astring_free,
2219 NULL);
2220 clist_free(resp_text_code->rc_data.rc_badcharset);
2221 }
2222 break;
2223 case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA:
2224 if (resp_text_code->rc_data.rc_cap_data != NULL)
2225 mailimap_capability_data_free(resp_text_code->rc_data.rc_cap_data);
2226 break;
2227 case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS:
2228 if (resp_text_code->rc_data.rc_perm_flags != NULL) {
2229 clist_foreach(resp_text_code->rc_data.rc_perm_flags,
2230 (clist_func) mailimap_flag_perm_free, NULL);
2231 clist_free(resp_text_code->rc_data.rc_perm_flags);
2232 }
2233 break;
2234 case MAILIMAP_RESP_TEXT_CODE_OTHER:
2235 if (resp_text_code->rc_data.rc_atom.atom_name != NULL)
2236 mailimap_atom_free(resp_text_code->rc_data.rc_atom.atom_name);
2237 if (resp_text_code->rc_data.rc_atom.atom_value != NULL)
2238 mailimap_custom_string_free(resp_text_code->rc_data.rc_atom.atom_value);
2239 break;
2240 }
2241 free(resp_text_code);
2242}
2243
2244
2245struct mailimap_section *
2246mailimap_section_new(struct mailimap_section_spec * sec_spec)
2247{
2248 struct mailimap_section * section;
2249
2250 section = malloc(sizeof(* section));
2251 if (section == NULL)
2252 return NULL;
2253
2254 section->sec_spec = sec_spec;
2255
2256 return section;
2257}
2258
2259void mailimap_section_free(struct mailimap_section * section)
2260{
2261 if (section->sec_spec != NULL)
2262 mailimap_section_spec_free(section->sec_spec);
2263 free(section);
2264}
2265
2266
2267
2268struct mailimap_section_msgtext *
2269mailimap_section_msgtext_new(int sec_type,
2270 struct mailimap_header_list * sec_header_list)
2271{
2272 struct mailimap_section_msgtext * msgtext;
2273
2274 msgtext = malloc(sizeof(* msgtext));
2275 if (msgtext == NULL)
2276 return FALSE;
2277
2278 msgtext->sec_type = sec_type;
2279 msgtext->sec_header_list = sec_header_list;
2280
2281 return msgtext;
2282}
2283
2284void
2285mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext)
2286{
2287 if (msgtext->sec_header_list != NULL)
2288 mailimap_header_list_free(msgtext->sec_header_list);
2289 free(msgtext);
2290}
2291
2292
2293struct mailimap_section_part *
2294mailimap_section_part_new(clist * sec_id)
2295{
2296 struct mailimap_section_part * section_part;
2297
2298 section_part = malloc(sizeof(* section_part));
2299 if (section_part == NULL)
2300 return NULL;
2301
2302 section_part->sec_id = sec_id;
2303
2304 return section_part;
2305}
2306
2307void
2308mailimap_section_part_free(struct mailimap_section_part * section_part)
2309{
2310 clist_foreach(section_part->sec_id,
2311 (clist_func) mailimap_number_alloc_free, NULL);
2312 clist_free(section_part->sec_id);
2313 free(section_part);
2314}
2315
2316
2317struct mailimap_section_spec *
2318mailimap_section_spec_new(int sec_type,
2319 struct mailimap_section_msgtext * sec_msgtext,
2320 struct mailimap_section_part * sec_part,
2321 struct mailimap_section_text * sec_text)
2322{
2323 struct mailimap_section_spec * section_spec;
2324
2325 section_spec = malloc(sizeof(* section_spec));
2326 if (section_spec == NULL)
2327 return NULL;
2328
2329 section_spec->sec_type = sec_type;
2330 switch (sec_type) {
2331 case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT:
2332 section_spec->sec_data.sec_msgtext = sec_msgtext;
2333 break;
2334 case MAILIMAP_SECTION_SPEC_SECTION_PART:
2335 section_spec->sec_data.sec_part = sec_part;
2336 break;
2337 }
2338 section_spec->sec_text = sec_text;
2339
2340 return section_spec;
2341}
2342
2343void
2344mailimap_section_spec_free(struct mailimap_section_spec * section_spec)
2345{
2346 if (section_spec->sec_text)
2347 mailimap_section_text_free(section_spec->sec_text);
2348
2349 switch (section_spec->sec_type) {
2350 case MAILIMAP_SECTION_SPEC_SECTION_PART:
2351 if (section_spec->sec_data.sec_part != NULL)
2352 mailimap_section_part_free(section_spec->sec_data.sec_part);
2353 break;
2354 case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT:
2355 /* handle case where it can be detached */
2356 if (section_spec->sec_data.sec_msgtext != NULL)
2357 mailimap_section_msgtext_free(section_spec->sec_data.sec_msgtext);
2358 break;
2359 }
2360 free(section_spec);
2361}
2362
2363
2364struct mailimap_section_text *
2365mailimap_section_text_new(int sec_type,
2366 struct mailimap_section_msgtext * sec_msgtext)
2367{
2368 struct mailimap_section_text * section_text;
2369
2370 section_text = malloc(sizeof(* section_text));
2371 if (section_text == NULL)
2372 return NULL;
2373
2374 section_text->sec_type = sec_type;
2375 section_text->sec_msgtext = sec_msgtext;
2376
2377 return section_text;
2378}
2379
2380void
2381mailimap_section_text_free(struct mailimap_section_text * section_text)
2382{
2383 if (section_text->sec_msgtext != NULL)
2384 mailimap_section_msgtext_free(section_text->sec_msgtext);
2385 free(section_text);
2386}
2387
2388
2389
2390
2391void
2392mailimap_string_free(char * str)
2393{
2394 mmap_string_unref(str);
2395}
2396
2397
2398
2399
2400
2401void mailimap_tag_free(char * tag)
2402{
2403 mailimap_custom_string_free(tag);
2404}
2405
2406
2407void mailimap_text_free(char * text)
2408{
2409 mailimap_custom_string_free(text);
2410}
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433/* ************************************************************************* */
2434/* ************************************************************************* */
2435/* ************************************************************************* */
2436/* ************************************************************************* */
2437/* ************************************************************************* */
2438/* ************************************************************************* */
2439
2440
2441
2442
2443
2444
2445/* sender only */
2446
2447
2448/* COPY FETCH SEARCH STORE */
2449/* set */
2450
2451struct mailimap_set_item *
2452mailimap_set_item_new(uint32_t set_first, uint32_t set_last)
2453{
2454 struct mailimap_set_item * item;
2455
2456 item = malloc(sizeof(* item));
2457 if (item == NULL)
2458 return NULL;
2459
2460 item->set_first = set_first;
2461 item->set_last = set_last;
2462
2463 return item;
2464}
2465
2466void mailimap_set_item_free(struct mailimap_set_item * set_item)
2467{
2468 free(set_item);
2469}
2470
2471struct mailimap_set * mailimap_set_new(clist * set_list)
2472{
2473 struct mailimap_set * set;
2474
2475 set = malloc(sizeof(* set));
2476 if (set == NULL)
2477 return NULL;
2478
2479 set->set_list = set_list;
2480
2481 return set;
2482}
2483
2484void mailimap_set_free(struct mailimap_set * set)
2485{
2486 clist_foreach(set->set_list, (clist_func) mailimap_set_item_free, NULL);
2487 clist_free(set->set_list);
2488 free(set);
2489}
2490
2491/* SEARCH with date key */
2492/* date */
2493
2494struct mailimap_date *
2495mailimap_date_new(int dt_day, int dt_month, int dt_year)
2496{
2497 struct mailimap_date * date;
2498
2499 date = malloc(sizeof(* date));
2500 if (date == NULL)
2501 return NULL;
2502
2503 date->dt_day = dt_day;
2504 date->dt_month = dt_month;
2505 date->dt_year = dt_year;
2506
2507 return date;
2508}
2509
2510void mailimap_date_free(struct mailimap_date * date)
2511{
2512 free(date);
2513}
2514
2515
2516
2517struct mailimap_fetch_att *
2518mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section,
2519 uint32_t att_offset, uint32_t att_size)
2520{
2521 struct mailimap_fetch_att * fetch_att;
2522
2523 fetch_att = malloc(sizeof(* fetch_att));
2524 if (fetch_att == NULL)
2525 return NULL;
2526 fetch_att->att_type = att_type;
2527 fetch_att->att_section = att_section;
2528 fetch_att->att_offset = att_offset;
2529 fetch_att->att_size = att_size;
2530
2531 return fetch_att;
2532}
2533
2534void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att)
2535{
2536 if (fetch_att->att_section != NULL)
2537 mailimap_section_free(fetch_att->att_section);
2538 free(fetch_att);
2539}
2540
2541
2542
2543struct mailimap_fetch_type *
2544mailimap_fetch_type_new(int ft_type,
2545 struct mailimap_fetch_att * ft_fetch_att,
2546 clist * ft_fetch_att_list)
2547{
2548 struct mailimap_fetch_type * fetch_type;
2549
2550 fetch_type = malloc(sizeof(* fetch_type));
2551 if (fetch_type == NULL)
2552 return NULL;
2553 fetch_type->ft_type = ft_type;
2554 switch (ft_type) {
2555 case MAILIMAP_FETCH_TYPE_FETCH_ATT:
2556 fetch_type->ft_data.ft_fetch_att = ft_fetch_att;
2557 break;
2558 case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST:
2559 fetch_type->ft_data.ft_fetch_att_list = ft_fetch_att_list;
2560 break;
2561 }
2562
2563 return fetch_type;
2564}
2565
2566void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type)
2567{
2568 switch (fetch_type->ft_type) {
2569 case MAILIMAP_FETCH_TYPE_FETCH_ATT:
2570 mailimap_fetch_att_free(fetch_type->ft_data.ft_fetch_att);
2571 break;
2572 case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST:
2573 clist_foreach(fetch_type->ft_data.ft_fetch_att_list,
2574 (clist_func) mailimap_fetch_att_free, NULL);
2575 clist_free(fetch_type->ft_data.ft_fetch_att_list);
2576 break;
2577 }
2578 free(fetch_type);
2579}
2580
2581
2582
2583
2584struct mailimap_store_att_flags *
2585mailimap_store_att_flags_new(int fl_sign, int fl_silent,
2586 struct mailimap_flag_list * fl_flag_list)
2587{
2588 struct mailimap_store_att_flags * store_att_flags;
2589
2590 store_att_flags = malloc(sizeof(* store_att_flags));
2591 if (store_att_flags == NULL)
2592 return NULL;
2593
2594 store_att_flags->fl_sign = fl_sign;
2595 store_att_flags->fl_silent = fl_silent;
2596 store_att_flags->fl_flag_list = fl_flag_list;
2597
2598 return store_att_flags;
2599}
2600
2601void mailimap_store_att_flags_free(struct mailimap_store_att_flags *
2602 store_att_flags)
2603{
2604 mailimap_flag_list_free(store_att_flags->fl_flag_list);
2605 free(store_att_flags);
2606}
2607
2608
2609struct mailimap_search_key *
2610mailimap_search_key_new(int sk_type,
2611 char * sk_bcc, struct mailimap_date * sk_before, char * sk_body,
2612 char * sk_cc, char * sk_from, char * sk_keyword,
2613 struct mailimap_date * sk_on, struct mailimap_date * sk_since,
2614 char * sk_subject, char * sk_text, char * sk_to,
2615 char * sk_unkeyword, char * sk_header_name,
2616 char * sk_header_value, uint32_t sk_larger,
2617 struct mailimap_search_key * sk_not,
2618 struct mailimap_search_key * sk_or1,
2619 struct mailimap_search_key * sk_or2,
2620 struct mailimap_date * sk_sentbefore,
2621 struct mailimap_date * sk_senton,
2622 struct mailimap_date * sk_sentsince,
2623 uint32_t sk_smaller, struct mailimap_set * sk_uid,
2624 struct mailimap_set * sk_set, clist * sk_multiple)
2625{
2626 struct mailimap_search_key * key;
2627
2628 key = malloc(sizeof(* key));
2629 if (key == NULL)
2630 return NULL;
2631
2632 key->sk_type = sk_type;
2633 switch (sk_type) {
2634 case MAILIMAP_SEARCH_KEY_BCC:
2635 key->sk_data.sk_bcc = sk_bcc;
2636 break;
2637 case MAILIMAP_SEARCH_KEY_BEFORE:
2638 key->sk_data.sk_before = sk_before;
2639 break;
2640 case MAILIMAP_SEARCH_KEY_BODY:
2641 key->sk_data.sk_body = sk_body;
2642 break;
2643 case MAILIMAP_SEARCH_KEY_CC:
2644 key->sk_data.sk_cc = sk_cc;
2645 break;
2646 case MAILIMAP_SEARCH_KEY_FROM:
2647 key->sk_data.sk_from = sk_from;
2648 break;
2649 case MAILIMAP_SEARCH_KEY_KEYWORD:
2650 key->sk_data.sk_keyword = sk_keyword;
2651 break;
2652 case MAILIMAP_SEARCH_KEY_ON:
2653 key->sk_data.sk_on = sk_on;
2654 break;
2655 case MAILIMAP_SEARCH_KEY_SINCE:
2656 key->sk_data.sk_since = sk_since;
2657 break;
2658 case MAILIMAP_SEARCH_KEY_SUBJECT:
2659 key->sk_data.sk_subject = sk_subject;
2660 break;
2661 case MAILIMAP_SEARCH_KEY_TEXT:
2662 key->sk_data.sk_text = sk_text;
2663 break;
2664 case MAILIMAP_SEARCH_KEY_TO:
2665 key->sk_data.sk_to = sk_to;
2666 break;
2667 case MAILIMAP_SEARCH_KEY_UNKEYWORD:
2668 key->sk_data.sk_unkeyword = sk_unkeyword;
2669 break;
2670 case MAILIMAP_SEARCH_KEY_HEADER:
2671 key->sk_data.sk_header.sk_header_name = sk_header_name;
2672 key->sk_data.sk_header.sk_header_value = sk_header_value;
2673 break;
2674 case MAILIMAP_SEARCH_KEY_LARGER:
2675 key->sk_data.sk_larger = sk_larger;
2676 break;
2677 case MAILIMAP_SEARCH_KEY_NOT:
2678 key->sk_data.sk_not = sk_not;
2679 break;
2680 case MAILIMAP_SEARCH_KEY_OR:
2681 key->sk_data.sk_or.sk_or1 = sk_or1;
2682 key->sk_data.sk_or.sk_or2 = sk_or2;
2683 break;
2684 case MAILIMAP_SEARCH_KEY_SENTBEFORE:
2685 key->sk_data.sk_sentbefore = sk_sentbefore;
2686 break;
2687 case MAILIMAP_SEARCH_KEY_SENTON:
2688 key->sk_data.sk_senton = sk_senton;
2689 break;
2690 case MAILIMAP_SEARCH_KEY_SENTSINCE:
2691 key->sk_data.sk_sentsince = sk_sentsince;
2692 break;
2693 case MAILIMAP_SEARCH_KEY_SMALLER:
2694 key->sk_data.sk_smaller = sk_smaller;
2695 break;
2696 case MAILIMAP_SEARCH_KEY_UID:
2697 key->sk_data.sk_uid = sk_uid;
2698 break;
2699 case MAILIMAP_SEARCH_KEY_SET:
2700 key->sk_data.sk_set = sk_set;
2701 break;
2702 case MAILIMAP_SEARCH_KEY_MULTIPLE:
2703 key->sk_data.sk_multiple = sk_multiple;
2704 break;
2705 }
2706 return key;
2707}
2708
2709
2710void mailimap_search_key_free(struct mailimap_search_key * key)
2711{
2712 switch (key->sk_type) {
2713 case MAILIMAP_SEARCH_KEY_BCC:
2714 mailimap_astring_free(key->sk_data.sk_bcc);
2715 break;
2716 case MAILIMAP_SEARCH_KEY_BEFORE:
2717 mailimap_date_free(key->sk_data.sk_before);
2718 break;
2719 case MAILIMAP_SEARCH_KEY_BODY:
2720 mailimap_astring_free(key->sk_data.sk_body);
2721 break;
2722 case MAILIMAP_SEARCH_KEY_CC:
2723 mailimap_astring_free(key->sk_data.sk_cc);
2724 break;
2725 case MAILIMAP_SEARCH_KEY_FROM:
2726 mailimap_astring_free(key->sk_data.sk_from);
2727 break;
2728 case MAILIMAP_SEARCH_KEY_KEYWORD:
2729 mailimap_flag_keyword_free(key->sk_data.sk_keyword);
2730 break;
2731 case MAILIMAP_SEARCH_KEY_ON:
2732 mailimap_date_free(key->sk_data.sk_on);
2733 break;
2734 case MAILIMAP_SEARCH_KEY_SINCE:
2735 mailimap_date_free(key->sk_data.sk_since);
2736 break;
2737 case MAILIMAP_SEARCH_KEY_SUBJECT:
2738 mailimap_astring_free(key->sk_data.sk_subject);
2739 break;
2740 case MAILIMAP_SEARCH_KEY_TEXT:
2741 mailimap_astring_free(key->sk_data.sk_text);
2742 break;
2743 case MAILIMAP_SEARCH_KEY_TO:
2744 mailimap_astring_free(key->sk_data.sk_to);
2745 break;
2746 case MAILIMAP_SEARCH_KEY_UNKEYWORD:
2747 mailimap_flag_keyword_free(key->sk_data.sk_unkeyword);
2748 break;
2749 case MAILIMAP_SEARCH_KEY_HEADER:
2750 mailimap_header_fld_name_free(key->sk_data.sk_header.sk_header_name);
2751 mailimap_astring_free(key->sk_data.sk_header.sk_header_value);
2752 break;
2753 case MAILIMAP_SEARCH_KEY_NOT:
2754 mailimap_search_key_free(key->sk_data.sk_not);
2755 break;
2756 case MAILIMAP_SEARCH_KEY_OR:
2757 mailimap_search_key_free(key->sk_data.sk_or.sk_or1);
2758 mailimap_search_key_free(key->sk_data.sk_or.sk_or2);
2759 break;
2760 case MAILIMAP_SEARCH_KEY_SENTBEFORE:
2761 mailimap_date_free(key->sk_data.sk_sentbefore);
2762 break;
2763 case MAILIMAP_SEARCH_KEY_SENTON:
2764 mailimap_date_free(key->sk_data.sk_senton);
2765 break;
2766 case MAILIMAP_SEARCH_KEY_SENTSINCE:
2767 mailimap_date_free(key->sk_data.sk_sentsince);
2768 break;
2769 case MAILIMAP_SEARCH_KEY_UID:
2770 mailimap_set_free(key->sk_data.sk_uid);
2771 break;
2772 case MAILIMAP_SEARCH_KEY_SET:
2773 mailimap_set_free(key->sk_data.sk_set);
2774 break;
2775 case MAILIMAP_SEARCH_KEY_MULTIPLE:
2776 clist_foreach(key->sk_data.sk_multiple,
2777 (clist_func) mailimap_search_key_free, NULL);
2778 clist_free(key->sk_data.sk_multiple);
2779 break;
2780 }
2781
2782 free(key);
2783}
2784
2785
2786
2787
2788
2789
2790
2791
2792struct mailimap_status_att_list *
2793mailimap_status_att_list_new(clist * att_list)
2794{
2795 struct mailimap_status_att_list * status_att_list;
2796
2797 status_att_list = malloc(sizeof(* status_att_list));
2798 if (status_att_list == NULL)
2799 return NULL;
2800 status_att_list->att_list = att_list;
2801
2802 return status_att_list;
2803}
2804
2805void mailimap_status_att_list_free(struct mailimap_status_att_list *
2806 status_att_list)
2807{
2808 clist_foreach(status_att_list->att_list, (clist_func) free, NULL);
2809 clist_free(status_att_list->att_list);
2810 free(status_att_list);
2811}
2812
2813
2814
2815
2816/* main */
2817
2818
2819struct mailimap_selection_info *
2820mailimap_selection_info_new(void)
2821{
2822 struct mailimap_selection_info * sel_info;
2823
2824 sel_info = malloc(sizeof(* sel_info));
2825 if (sel_info == NULL)
2826 return NULL;
2827
2828 sel_info->sel_perm_flags = NULL;
2829 sel_info->sel_perm = MAILIMAP_MAILBOX_READWRITE;
2830 sel_info->sel_uidnext = 0;
2831 sel_info->sel_uidvalidity = 0;
2832 sel_info->sel_first_unseen = 0;
2833 sel_info->sel_flags = NULL;
2834 sel_info->sel_exists = 0;
2835 sel_info->sel_recent = 0;
2836 sel_info->sel_unseen = 0;
2837
2838 return sel_info;
2839}
2840
2841void
2842mailimap_selection_info_free(struct mailimap_selection_info * sel_info)
2843{
2844 if (sel_info->sel_perm_flags != NULL) {
2845 clist_foreach(sel_info->sel_perm_flags,
2846 (clist_func) mailimap_flag_perm_free, NULL);
2847 clist_free(sel_info->sel_perm_flags);
2848 }
2849 if (sel_info->sel_flags)
2850 mailimap_flag_list_free(sel_info->sel_flags);
2851
2852 free(sel_info);
2853}
2854
2855struct mailimap_connection_info *
2856mailimap_connection_info_new(void)
2857{
2858 struct mailimap_connection_info * conn_info;
2859
2860 conn_info = malloc(sizeof(* conn_info));
2861 if (conn_info == NULL)
2862 return NULL;
2863
2864 conn_info->imap_capability = NULL;
2865
2866 return conn_info;
2867}
2868
2869void
2870mailimap_connection_info_free(struct mailimap_connection_info * conn_info)
2871{
2872 if (conn_info->imap_capability != NULL)
2873 mailimap_capability_data_free(conn_info->imap_capability);
2874 free(conn_info);
2875}
2876
2877struct mailimap_response_info *
2878mailimap_response_info_new(void)
2879{
2880 struct mailimap_response_info * resp_info;
2881
2882 resp_info = malloc(sizeof(* resp_info));
2883 if (resp_info == NULL)
2884 goto err;
2885
2886 resp_info->rsp_alert = NULL;
2887 resp_info->rsp_parse = NULL;
2888 resp_info->rsp_badcharset = NULL;
2889 resp_info->rsp_trycreate = FALSE;
2890 resp_info->rsp_mailbox_list = clist_new();
2891 if (resp_info->rsp_mailbox_list == NULL)
2892 goto free;
2893 resp_info->rsp_mailbox_lsub = clist_new();
2894 if (resp_info->rsp_mailbox_lsub == NULL)
2895 goto free_mb_list;
2896 resp_info->rsp_search_result = clist_new();
2897 if (resp_info->rsp_search_result == NULL)
2898 goto free_mb_lsub;
2899 resp_info->rsp_status = NULL;
2900 resp_info->rsp_expunged = clist_new();
2901 if (resp_info->rsp_expunged == NULL)
2902 goto free_search_result;
2903 resp_info->rsp_fetch_list = clist_new();
2904 if (resp_info->rsp_fetch_list == NULL)
2905 goto free_expunged;
2906
2907 return resp_info;
2908
2909 free_expunged:
2910 clist_free(resp_info->rsp_expunged);
2911 free_search_result:
2912 clist_free(resp_info->rsp_search_result);
2913 free_mb_lsub:
2914 clist_free(resp_info->rsp_mailbox_lsub);
2915 free_mb_list:
2916 clist_free(resp_info->rsp_mailbox_list);
2917 free:
2918 free(resp_info);
2919 err:
2920 return NULL;
2921}
2922
2923void
2924mailimap_response_info_free(struct mailimap_response_info * resp_info)
2925{
2926 if (resp_info->rsp_alert != NULL)
2927 free(resp_info->rsp_alert);
2928 if (resp_info->rsp_parse != NULL)
2929 free(resp_info->rsp_parse);
2930 if (resp_info->rsp_badcharset != NULL) {
2931 clist_foreach(resp_info->rsp_badcharset,
2932 (clist_func) mailimap_astring_free, NULL);
2933 clist_free(resp_info->rsp_badcharset);
2934 }
2935 if (resp_info->rsp_mailbox_list != NULL) {
2936 clist_foreach(resp_info->rsp_mailbox_list,
2937 (clist_func) mailimap_mailbox_list_free, NULL);
2938 clist_free(resp_info->rsp_mailbox_list);
2939 }
2940 if (resp_info->rsp_mailbox_lsub != NULL) {
2941 clist_foreach(resp_info->rsp_mailbox_lsub,
2942 (clist_func) mailimap_mailbox_list_free, NULL);
2943 clist_free(resp_info->rsp_mailbox_lsub);
2944 }
2945 if (resp_info->rsp_search_result != NULL)
2946 mailimap_mailbox_data_search_free(resp_info->rsp_search_result);
2947 if (resp_info->rsp_status != NULL)
2948 mailimap_mailbox_data_status_free(resp_info->rsp_status);
2949 if (resp_info->rsp_expunged != NULL) {
2950 clist_foreach(resp_info->rsp_expunged,
2951 (clist_func) mailimap_number_alloc_free, NULL);
2952 clist_free(resp_info->rsp_expunged);
2953 }
2954 if (resp_info->rsp_fetch_list != NULL) {
2955 clist_foreach(resp_info->rsp_fetch_list,
2956 (clist_func) mailimap_msg_att_free, NULL);
2957 clist_free(resp_info->rsp_fetch_list);
2958 }
2959
2960 free(resp_info);
2961}
diff --git a/libetpan/src/low-level/imap/mailimap_types.h b/libetpan/src/low-level/imap/mailimap_types.h
new file mode 100644
index 0000000..532d2c0
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_types.h
@@ -0,0 +1,3274 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 IMAP4rev1 grammar
38
39 address = "(" addr-name SP addr-adl SP addr-mailbox SP
40 addr-host ")"
41
42 addr-adl = nstring
43 ; Holds route from [RFC-822] route-addr if
44 ; non-NIL
45
46 addr-host = nstring
47 ; NIL indicates [RFC-822] group syntax.
48 ; Otherwise, holds [RFC-822] domain name
49
50 addr-mailbox = nstring
51 ; NIL indicates end of [RFC-822] group; if
52 ; non-NIL and addr-host is NIL, holds
53 ; [RFC-822] group name.
54 ; Otherwise, holds [RFC-822] local-part
55 ; after removing [RFC-822] quoting
56
57
58
59 addr-name = nstring
60 ; If non-NIL, holds phrase from [RFC-822]
61 ; mailbox after removing [RFC-822] quoting
62
63 append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
64 literal
65
66 astring = 1*ASTRING-CHAR / string
67
68 ASTRING-CHAR = ATOM-CHAR / resp-specials
69
70 atom = 1*ATOM-CHAR
71
72 ATOM-CHAR = <any CHAR except atom-specials>
73
74 atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
75 quoted-specials / resp-specials
76
77 authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
78
79 auth-type = atom
80 ; Defined by [SASL]
81
82 base64 = *(4base64-char) [base64-terminal]
83
84 base64-char = ALPHA / DIGIT / "+" / "/"
85 ; Case-sensitive
86
87 base64-terminal = (2base64-char "==") / (3base64-char "=")
88
89 body = "(" (body-type-1part / body-type-mpart) ")"
90
91 body-extension = nstring / number /
92 "(" body-extension *(SP body-extension) ")"
93 ; Future expansion. Client implementations
94 ; MUST accept body-extension fields. Server
95 ; implementations MUST NOT generate
96 ; body-extension fields except as defined by
97 ; future standard or standards-track
98 ; revisions of this specification.
99
100 body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
101 *(SP body-extension)]]
102 ; MUST NOT be returned on non-extensible
103 ; "BODY" fetch
104
105
106 body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
107 *(SP body-extension)]]
108 ; MUST NOT be returned on non-extensible
109 ; "BODY" fetch
110
111 body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
112 body-fld-enc SP body-fld-octets
113
114 body-fld-desc = nstring
115
116 body-fld-dsp = "(" string SP body-fld-param ")" / nil
117
118 body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
119 "QUOTED-PRINTABLE") DQUOTE) / string
120
121 body-fld-id = nstring
122
123 body-fld-lang = nstring / "(" string *(SP string) ")"
124
125 body-fld-lines = number
126
127 body-fld-md5 = nstring
128
129 body-fld-octets = number
130
131 body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
132
133 body-type-1part = (body-type-basic / body-type-msg / body-type-text)
134 [SP body-ext-1part]
135
136 body-type-basic = media-basic SP body-fields
137 ; MESSAGE subtype MUST NOT be "RFC822"
138
139 body-type-mpart = 1*body SP media-subtype
140 [SP body-ext-mpart]
141
142 body-type-msg = media-message SP body-fields SP envelope
143 SP body SP body-fld-lines
144
145 body-type-text = media-text SP body-fields SP body-fld-lines
146
147 capability = ("AUTH=" auth-type) / atom
148 ; New capabilities MUST begin with "X" or be
149 ; registered with IANA as standard or
150 ; standards-track
151
152
153 capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
154 *(SP capability)
155 ; IMAP4rev1 servers which offer RFC 1730
156 ; compatibility MUST list "IMAP4" as the first
157 ; capability.
158
159 CHAR8 = %x01-ff
160 ; any OCTET except NUL, %x00
161
162 command = tag SP (command-any / command-auth / command-nonauth /
163 command-select) CRLF
164 ; Modal based on state
165
166 command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
167 ; Valid in all states
168
169 command-auth = append / create / delete / examine / list / lsub /
170 rename / select / status / subscribe / unsubscribe
171 ; Valid only in Authenticated or Selected state
172
173 command-nonauth = login / authenticate
174 ; Valid only when in Not Authenticated state
175
176 command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
177 uid / search
178 ; Valid only when in Selected state
179
180 continue-req = "+" SP (resp-text / base64) CRLF
181
182 copy = "COPY" SP set SP mailbox
183
184 create = "CREATE" SP mailbox
185 ; Use of INBOX gives a NO error
186
187 date = date-text / DQUOTE date-text DQUOTE
188
189 date-day = 1*2DIGIT
190 ; Day of month
191
192 date-day-fixed = (SP DIGIT) / 2DIGIT
193 ; Fixed-format version of date-day
194
195 date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
196 "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
197
198 date-text = date-day "-" date-month "-" date-year
199
200 date-year = 4DIGIT
201
202 date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
203 SP time SP zone DQUOTE
204
205 delete = "DELETE" SP mailbox
206 ; Use of INBOX gives a NO error
207
208 digit-nz = %x31-39
209 ; 1-9
210
211 envelope = "(" env-date SP env-subject SP env-from SP env-sender SP
212 env-reply-to SP env-to SP env-cc SP env-bcc SP
213 env-in-reply-to SP env-message-id ")"
214
215 env-bcc = "(" 1*address ")" / nil
216
217 env-cc = "(" 1*address ")" / nil
218
219 env-date = nstring
220
221 env-from = "(" 1*address ")" / nil
222
223 env-in-reply-to = nstring
224
225 env-message-id = nstring
226
227 env-reply-to = "(" 1*address ")" / nil
228
229 env-sender = "(" 1*address ")" / nil
230
231 env-subject = nstring
232
233 env-to = "(" 1*address ")" / nil
234
235 examine = "EXAMINE" SP mailbox
236
237 fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att /
238 "(" fetch-att *(SP fetch-att) ")")
239
240 fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
241 "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
242 "BODY" ["STRUCTURE"] / "UID" /
243 "BODY" [".PEEK"] section ["<" number "." nz-number ">"]
244
245 flag = "\Answered" / "\Flagged" / "\Deleted" /
246 "\Seen" / "\Draft" / flag-keyword / flag-extension
247 ; Does not include "\Recent"
248
249 flag-extension = "\" atom
250 ; Future expansion. Client implementations
251 ; MUST accept flag-extension flags. Server
252 ; implementations MUST NOT generate
253 ; flag-extension flags except as defined by
254 ; future standard or standards-track
255 ; revisions of this specification.
256
257 flag-fetch = flag / "\Recent"
258
259 flag-keyword = atom
260
261 flag-list = "(" [flag *(SP flag)] ")"
262
263 flag-perm = flag / "\*"
264
265 greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
266
267 header-fld-name = astring
268
269 header-list = "(" header-fld-name *(SP header-fld-name) ")"
270
271 list = "LIST" SP mailbox SP list-mailbox
272
273 list-mailbox = 1*list-char / string
274
275 list-char = ATOM-CHAR / list-wildcards / resp-specials
276
277 list-wildcards = "%" / "*"
278
279 literal = "{" number "}" CRLF *CHAR8
280 ; Number represents the number of CHAR8s
281
282 login = "LOGIN" SP userid SP password
283
284 lsub = "LSUB" SP mailbox SP list-mailbox
285
286 mailbox = "INBOX" / astring
287 ; INBOX is case-insensitive. All case variants of
288 ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
289 ; not as an astring. An astring which consists of
290 ; the case-insensitive sequence "I" "N" "B" "O" "X"
291 ; is considered to be INBOX and not an astring.
292 ; Refer to section 5.1 for further
293 ; semantic details of mailbox names.
294
295 mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
296 "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
297 "STATUS" SP mailbox SP "("
298 [status-att SP number *(SP status-att SP number)] ")" /
299 number SP "EXISTS" / number SP "RECENT"
300
301 mailbox-list = "(" [mbx-list-flags] ")" SP
302 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
303
304 mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
305 *(SP mbx-list-oflag) /
306 mbx-list-oflag *(SP mbx-list-oflag)
307
308 mbx-list-oflag = "\Noinferiors" / flag-extension
309 ; Other flags; multiple possible per LIST response
310
311 mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
312 ; Selectability flags; only one per LIST response
313
314 media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" /
315 "VIDEO") DQUOTE) / string) SP media-subtype
316 ; Defined in [MIME-IMT]
317
318 media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
319 ; Defined in [MIME-IMT]
320
321 media-subtype = string
322 ; Defined in [MIME-IMT]
323
324 media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
325 ; Defined in [MIME-IMT]
326
327 message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
328
329 msg-att = "(" (msg-att-dynamic / msg-att-static)
330 *(SP (msg-att-dynamic / msg-att-static)) ")"
331
332 msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
333 ; MAY change for a message
334
335 msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
336 "RFC822" [".HEADER" / ".TEXT"] SP nstring /
337 "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body /
338 "BODY" section ["<" number ">"] SP nstring /
339 "UID" SP uniqueid
340 ; MUST NOT change for a message
341
342 nil = "NIL"
343
344 nstring = string / nil
345
346 number = 1*DIGIT
347 ; Unsigned 32-bit integer
348 ; (0 <= n < 4,294,967,296)
349
350 nz-number = digit-nz *DIGIT
351 ; Non-zero unsigned 32-bit integer
352 ; (0 < n < 4,294,967,296)
353
354 password = astring
355
356 quoted = DQUOTE *QUOTED-CHAR DQUOTE
357
358 QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
359 "\" quoted-specials
360
361 quoted-specials = DQUOTE / "\"
362
363 rename = "RENAME" SP mailbox SP mailbox
364 ; Use of INBOX as a destination gives a NO error
365
366 response = *(continue-req / response-data) response-done
367
368 response-data = "*" SP (resp-cond-state / resp-cond-bye /
369 mailbox-data / message-data / capability-data) CRLF
370
371 response-done = response-tagged / response-fatal
372
373 response-fatal = "*" SP resp-cond-bye CRLF
374 ; Server closes connection immediately
375
376 response-tagged = tag SP resp-cond-state CRLF
377
378 resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
379 ; Authentication condition
380
381 resp-cond-bye = "BYE" SP resp-text
382
383 resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
384 ; Status condition
385
386 resp-specials = "]"
387
388 resp-text = ["[" resp-text-code "]" SP] text
389
390 resp-text-code = "ALERT" /
391 "BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
392 capability-data / "PARSE" /
393 "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
394 "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
395 "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
396 "UNSEEN" SP nz-number /
397 atom [SP 1*<any TEXT-CHAR except "]">]
398
399 search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
400 ; CHARSET argument to MUST be registered with IANA
401
402 search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
403 "BEFORE" SP date / "BODY" SP astring /
404 "CC" SP astring / "DELETED" / "FLAGGED" /
405 "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" /
406 "OLD" / "ON" SP date / "RECENT" / "SEEN" /
407 "SINCE" SP date / "SUBJECT" SP astring /
408 "TEXT" SP astring / "TO" SP astring /
409 "UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
410 "UNKEYWORD" SP flag-keyword / "UNSEEN" /
411 ; Above this line were in [IMAP2]
412 "DRAFT" / "HEADER" SP header-fld-name SP astring /
413 "LARGER" SP number / "NOT" SP search-key /
414 "OR" SP search-key SP search-key /
415 "SENTBEFORE" SP date / "SENTON" SP date /
416 "SENTSINCE" SP date / "SMALLER" SP number /
417 "UID" SP set / "UNDRAFT" / set /
418 "(" search-key *(SP search-key) ")"
419
420 section = "[" [section-spec] "]"
421
422 section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
423 "TEXT"
424 ; top-level or MESSAGE/RFC822 part
425
426 section-part = nz-number *("." nz-number)
427 ; body part nesting
428
429 section-spec = section-msgtext / (section-part ["." section-text])
430
431 section-text = section-msgtext / "MIME"
432 ; text other than actual body part (headers, etc.)
433
434 select = "SELECT" SP mailbox
435
436 sequence-num = nz-number / "*"
437 ; * is the largest number in use. For message
438 ; sequence numbers, it is the number of messages
439 ; in the mailbox. For unique identifiers, it is
440 ; the unique identifier of the last message in
441 ; the mailbox.
442
443 set = sequence-num / (sequence-num ":" sequence-num) /
444 (set "," set)
445 ; Identifies a set of messages. For message
446 ; sequence numbers, these are consecutive
447 ; numbers from 1 to the number of messages in
448 ; the mailbox
449 ; Comma delimits individual numbers, colon
450 ; delimits between two numbers inclusive.
451 ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
452 ; 14,15 for a mailbox with 15 messages.
453
454
455 status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
456
457 status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
458 "UNSEEN"
459
460 store = "STORE" SP set SP store-att-flags
461
462 store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
463 (flag-list / (flag *(SP flag)))
464
465 string = quoted / literal
466
467 subscribe = "SUBSCRIBE" SP mailbox
468
469 tag = 1*<any ASTRING-CHAR except "+">
470
471 text = 1*TEXT-CHAR
472
473 TEXT-CHAR = <any CHAR except CR and LF>
474
475 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
476 ; Hours minutes seconds
477
478 uid = "UID" SP (copy / fetch / search / store)
479 ; Unique identifiers used instead of message
480 ; sequence numbers
481
482 uniqueid = nz-number
483 ; Strictly ascending
484
485 unsubscribe = "UNSUBSCRIBE" SP mailbox
486
487 userid = astring
488
489 x-command = "X" atom <experimental command arguments>
490
491 zone = ("+" / "-") 4DIGIT
492 ; Signed four-digit value of hhmm representing
493 ; hours and minutes east of Greenwich (that is,
494 ; the amount that the given time differs from
495 ; Universal Time). Subtracting the timezone
496 ; from the given time will give the UT form.
497 ; The Universal Time zone is "+0000".
498*/
499
500
501#ifndef MAILIMAP_TYPES_H
502
503#define MAILIMAP_TYPES_H
504
505#ifdef __cplusplus
506extern "C" {
507#endif
508
509#include <inttypes.h>
510#include <libetpan/mailstream.h>
511#include <libetpan/clist.h>
512
513
514/*
515 IMPORTANT NOTE:
516
517 All allocation functions will take as argument allocated data
518 and will store these data in the structure they will allocate.
519 Data should be persistant during all the use of the structure
520 and will be freed by the free function of the structure
521
522 allocation functions will return NULL on failure
523*/
524
525
526/*
527 mailimap_address represents a mail address
528
529 - personal_name is the name to display in an address
530 '"name"' in '"name" <address@domain>', should be allocated
531 with a malloc()
532
533 - source_route is the source-route information in the
534 mail address (RFC 822), should be allocated with a malloc()
535
536 - mailbox_name is the name of the mailbox 'address' in
537 '"name" <address@domain>', should be allocated with a malloc()
538
539 - host_name is the name of the host 'domain' in
540 '"name" <address@domain>', should be allocated with a malloc()
541
542 if mailbox_name is not NULL and host_name is NULL, this is the name
543 of a group, the next addresses in the list are elements of the group
544 until we reach an address with a NULL mailbox_name.
545*/
546
547struct mailimap_address {
548 char * ad_personal_name; /* can be NULL */
549 char * ad_source_route; /* can be NULL */
550 char * ad_mailbox_name; /* can be NULL */
551 char * ad_host_name; /* can be NULL */
552};
553
554
555struct mailimap_address *
556mailimap_address_new(char * ad_personal_name, char * ad_source_route,
557 char * ad_mailbox_name, char * ad_host_name);
558
559void mailimap_address_free(struct mailimap_address * addr);
560
561
562/* this is the type of MIME body parsed by IMAP server */
563
564enum {
565 MAILIMAP_BODY_ERROR,
566 MAILIMAP_BODY_1PART, /* single part */
567 MAILIMAP_BODY_MPART, /* multi-part */
568};
569
570/*
571 mailimap_body represent a MIME body parsed by IMAP server
572
573 - type is the type of the MIME part (single part or multipart)
574
575 - body_1part is defined if this is a single part
576
577 - body_mpart is defined if this is a multipart
578*/
579
580struct mailimap_body {
581 int bd_type;
582 /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */
583 union {
584 struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */
585 struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */
586 } bd_data;
587};
588
589
590struct mailimap_body *
591mailimap_body_new(int bd_type,
592 struct mailimap_body_type_1part * bd_body_1part,
593 struct mailimap_body_type_mpart * bd_body_mpart);
594
595void mailimap_body_free(struct mailimap_body * body);
596
597
598
599/*
600 this is the type of MIME body extension
601*/
602
603enum {
604 MAILIMAP_BODY_EXTENSION_ERROR,
605 MAILIMAP_BODY_EXTENSION_NSTRING, /* string */
606 MAILIMAP_BODY_EXTENSION_NUMBER, /* number */
607 MAILIMAP_BODY_EXTENSION_LIST, /* list of
608 (struct mailimap_body_extension *) */
609};
610
611/*
612 mailimap_body_extension is a future extension header field value
613
614 - type is the type of the body extension (string, number or
615 list of extension)
616
617 - nstring is a string value if the type is string
618
619 - number is a integer value if the type is number
620
621 - list is a list of body extension if the type is a list
622*/
623
624struct mailimap_body_extension {
625 int ext_type;
626 /*
627 can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER
628 or MAILIMAP_BODY_EXTENSION_LIST
629 */
630 union {
631 char * ext_nstring; /* can be NULL */
632 uint32_t ext_number;
633 clist * ext_body_extension_list;
634 /* list of (struct mailimap_body_extension *) */
635 /* can be NULL */
636 } ext_data;
637};
638
639struct mailimap_body_extension *
640mailimap_body_extension_new(int ext_type, char * ext_nstring,
641 uint32_t ext_number,
642 clist * ext_body_extension_list);
643
644void mailimap_body_extension_free(struct mailimap_body_extension * be);
645
646
647/*
648 mailimap_body_ext_1part is the extended result part of a single part
649 bodystructure.
650
651 - body_md5 is the value of the Content-MD5 header field, should be
652 allocated with malloc()
653
654 - body_disposition is the value of the Content-Disposition header field
655
656 - body_language is the value of the Content-Language header field
657
658 - body_extension_list is the list of extension fields value.
659*/
660
661struct mailimap_body_ext_1part {
662 char * bd_md5; /* != NULL */
663 struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */
664 struct mailimap_body_fld_lang * bd_language; /* can be NULL */
665
666 clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */
667 /* can be NULL */
668};
669
670struct mailimap_body_ext_1part *
671mailimap_body_ext_1part_new(char * bd_md5,
672 struct mailimap_body_fld_dsp * bd_disposition,
673 struct mailimap_body_fld_lang * bd_language,
674 clist * bd_extension_list);
675
676
677void
678mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part);
679
680
681/*
682 mailimap_body_ext_mpart is the extended result part of a multipart
683 bodystructure.
684
685 - body_parameter is the list of parameters of Content-Type header field
686
687 - body_disposition is the value of Content-Disposition header field
688
689 - body_language is the value of Content-Language header field
690
691 - body_extension_list is the list of extension fields value.
692*/
693
694struct mailimap_body_ext_mpart {
695 struct mailimap_body_fld_param * bd_parameter; /* != NULL */
696 struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */
697 struct mailimap_body_fld_lang * bd_language; /* can be NULL */
698 clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */
699 /* can be NULL */
700};
701
702struct mailimap_body_ext_mpart *
703mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter,
704 struct mailimap_body_fld_dsp * bd_disposition,
705 struct mailimap_body_fld_lang * bd_language,
706 clist * bd_extension_list);
707
708void
709mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart);
710
711
712/*
713 mailimap_body_fields is the MIME fields of a MIME part.
714
715 - body_parameter is the list of parameters of Content-Type header field
716
717 - body_id is the value of Content-ID header field, should be allocated
718 with malloc()
719
720 - body_description is the value of Content-Description header field,
721 should be allocated with malloc()
722
723 - body_encoding is the value of Content-Transfer-Encoding header field
724
725 - body_disposition is the value of Content-Disposition header field
726
727 - body_size is the size of the MIME part
728*/
729
730struct mailimap_body_fields {
731 struct mailimap_body_fld_param * bd_parameter; /* != NULL */
732 char * bd_id; /* can be NULL */
733 char * bd_description; /* can be NULL */
734 struct mailimap_body_fld_enc * bd_encoding; /* != NULL */
735 uint32_t bd_size;
736};
737
738struct mailimap_body_fields *
739mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter,
740 char * bd_id,
741 char * bd_description,
742 struct mailimap_body_fld_enc * bd_encoding,
743 uint32_t bd_size);
744
745void
746mailimap_body_fields_free(struct mailimap_body_fields * body_fields);
747
748
749
750/*
751 mailimap_body_fld_dsp is the parsed value of the Content-Disposition field
752
753 - disposition_type is the type of Content-Disposition
754 (usually attachment or inline), should be allocated with malloc()
755
756 - attributes is the list of Content-Disposition attributes
757*/
758
759struct mailimap_body_fld_dsp {
760 char * dsp_type; /* != NULL */
761 struct mailimap_body_fld_param * dsp_attributes; /* != NULL */
762};
763
764struct mailimap_body_fld_dsp *
765mailimap_body_fld_dsp_new(char * dsp_type,
766 struct mailimap_body_fld_param * dsp_attributes);
767
768void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd);
769
770
771
772/* these are the different parsed values for Content-Transfer-Encoding */
773
774enum {
775 MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */
776 MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */
777 MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */
778 MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */
779 MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */
780 MAILIMAP_BODY_FLD_ENC_OTHER, /* other */
781};
782
783/*
784 mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding
785
786 - type is the kind of Content-Transfer-Encoding, this can be
787 MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT,
788 MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64,
789 MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER
790
791 - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined,
792 should be allocated with malloc()
793*/
794
795struct mailimap_body_fld_enc {
796 int enc_type;
797 char * enc_value; /* can be NULL */
798};
799
800struct mailimap_body_fld_enc *
801mailimap_body_fld_enc_new(int enc_type, char * enc_value);
802
803void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe);
804
805
806/* this is the type of Content-Language header field value */
807
808enum {
809 MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */
810 MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */
811 MAILIMAP_BODY_FLD_LANG_LIST /* list of values */
812};
813
814/*
815 mailimap_body_fld_lang is the parsed value of the Content-Language field
816
817 - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE
818 if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are
819 several values
820
821 - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE,
822 should be allocated with malloc()
823
824 - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST,
825 all elements of the list should be allocated with malloc()
826*/
827
828struct mailimap_body_fld_lang {
829 int lg_type;
830 union {
831 char * lg_single; /* can be NULL */
832 clist * lg_list; /* list of string (char *), can be NULL */
833 } lg_data;
834};
835
836struct mailimap_body_fld_lang *
837mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list);
838
839void
840mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang);
841
842
843
844/*
845 mailimap_single_body_fld_param is a body field parameter
846
847 - name is the name of the parameter, should be allocated with malloc()
848
849 - value is the value of the parameter, should be allocated with malloc()
850*/
851
852struct mailimap_single_body_fld_param {
853 char * pa_name; /* != NULL */
854 char * pa_value; /* != NULL */
855};
856
857struct mailimap_single_body_fld_param *
858mailimap_single_body_fld_param_new(char * pa_name, char * pa_value);
859
860void
861mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p);
862
863
864/*
865 mailmap_body_fld_param is a list of parameters
866
867 - list is the list of parameters.
868*/
869
870struct mailimap_body_fld_param {
871 clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */
872 /* != NULL */
873};
874
875struct mailimap_body_fld_param *
876mailimap_body_fld_param_new(clist * pa_list);
877
878void
879mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param);
880
881
882/*
883 this is the kind of single part: a text part
884 (when Content-Type is text/xxx), a message part (when Content-Type is
885 message/rfc2822) or a basic part (others than multpart/xxx)
886*/
887
888enum {
889 MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */
890 MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */
891 MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */
892 MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */
893};
894
895
896/*
897 mailimap_body_type_1part is
898
899 - type is the kind of single part, this can be
900 MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or
901 MAILIMAP_BODY_TYPE_1PART_TEXT.
902
903 - body_type_basic is the basic part when type is
904 MAILIMAP_BODY_TYPE_1PART_BASIC
905
906 - body_type_msg is the message part when type is
907 MAILIMAP_BODY_TYPE_1PART_MSG
908
909 - body_type_text is the text part when type is
910 MAILIMAP_BODY_TYPE_1PART_TEXT
911*/
912
913struct mailimap_body_type_1part {
914 int bd_type;
915 union {
916 struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */
917 struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */
918 struct mailimap_body_type_text * bd_type_text; /* can be NULL */
919 } bd_data;
920 struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */
921};
922
923struct mailimap_body_type_1part *
924mailimap_body_type_1part_new(int bd_type,
925 struct mailimap_body_type_basic * bd_type_basic,
926 struct mailimap_body_type_msg * bd_type_msg,
927 struct mailimap_body_type_text * bd_type_text,
928 struct mailimap_body_ext_1part * bd_ext_1part);
929
930void
931mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p);
932
933
934
935/*
936 mailimap_body_type_basic is a basic field (with Content-Type other
937 than multipart/xxx, message/rfc2822 and text/xxx
938
939 - media_basic will be the MIME type of the part
940
941 - body_fields will be the parsed fields of the MIME part
942*/
943
944struct mailimap_body_type_basic {
945 struct mailimap_media_basic * bd_media_basic; /* != NULL */
946 struct mailimap_body_fields * bd_fields; /* != NULL */
947};
948
949struct mailimap_body_type_basic *
950mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic,
951 struct mailimap_body_fields * bd_fields);
952
953void mailimap_body_type_basic_free(struct mailimap_body_type_basic *
954 body_type_basic);
955
956/*
957 mailimap_body_type_mpart is a MIME multipart.
958
959 - body_list is the list of sub-parts.
960
961 - media_subtype is the subtype of the multipart (for example
962 in multipart/alternative, this is "alternative")
963
964 - body_ext_mpart is the extended fields of the MIME multipart
965*/
966
967struct mailimap_body_type_mpart {
968 clist * bd_list; /* list of (struct mailimap_body *) */
969 /* != NULL */
970 char * bd_media_subtype; /* != NULL */
971 struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */
972};
973
974struct mailimap_body_type_mpart *
975mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype,
976 struct mailimap_body_ext_mpart * bd_ext_mpart);
977
978void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart *
979 body_type_mpart);
980
981/*
982 mailimap_body_type_msg is a MIME message part
983
984 - body_fields is the MIME fields of the MIME message part
985
986 - envelope is the list of parsed RFC 822 fields of the MIME message
987
988 - body is the sub-part of the message
989
990 - body_lines is the number of lines of the message part
991*/
992
993struct mailimap_body_type_msg {
994 struct mailimap_body_fields * bd_fields; /* != NULL */
995 struct mailimap_envelope * bd_envelope; /* != NULL */
996 struct mailimap_body * bd_body; /* != NULL */
997 uint32_t bd_lines;
998};
999
1000struct mailimap_body_type_msg *
1001mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields,
1002 struct mailimap_envelope * bd_envelope,
1003 struct mailimap_body * bd_body,
1004 uint32_t bd_lines);
1005
1006void
1007mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg);
1008
1009
1010
1011/*
1012 mailimap_body_type_text is a single MIME part where Content-Type is text/xxx
1013
1014 - media-text is the subtype of the text part (for example, in "text/plain",
1015 this is "plain", should be allocated with malloc()
1016
1017 - body_fields is the MIME fields of the MIME message part
1018
1019 - body_lines is the number of lines of the message part
1020*/
1021
1022struct mailimap_body_type_text {
1023 char * bd_media_text; /* != NULL */
1024 struct mailimap_body_fields * bd_fields; /* != NULL */
1025 uint32_t bd_lines;
1026};
1027
1028struct mailimap_body_type_text *
1029mailimap_body_type_text_new(char * bd_media_text,
1030 struct mailimap_body_fields * bd_fields,
1031 uint32_t bd_lines);
1032
1033void
1034mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text);
1035
1036
1037
1038/* this is the type of capability field */
1039
1040enum {
1041 MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an
1042 authentication type */
1043 MAILIMAP_CAPABILITY_NAME, /* other type of capability */
1044};
1045
1046/*
1047 mailimap_capability is a capability of the IMAP server
1048
1049 - type is the type of capability, this is either a authentication type
1050 (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability
1051 (MAILIMAP_CAPABILITY_NAME)
1052
1053 - auth_type is a type of authentication "name" in "AUTH=name",
1054 auth_type can be for example "PLAIN", when this is an authentication type,
1055 should be allocated with malloc()
1056
1057 - name is a type of capability when this is not an authentication type,
1058 should be allocated with malloc()
1059*/
1060
1061struct mailimap_capability {
1062 int cap_type;
1063 union {
1064 char * cap_auth_type; /* can be NULL */
1065 char * cap_name; /* can be NULL */
1066 } cap_data;
1067};
1068
1069struct mailimap_capability *
1070mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name);
1071
1072void mailimap_capability_free(struct mailimap_capability * c);
1073
1074
1075
1076
1077/*
1078 mailimap_capability_data is a list of capability
1079
1080 - list is the list of capability
1081*/
1082
1083struct mailimap_capability_data {
1084 clist * cap_list; /* list of (struct mailimap_capability *), != NULL */
1085};
1086
1087struct mailimap_capability_data *
1088mailimap_capability_data_new(clist * cap_list);
1089
1090void
1091mailimap_capability_data_free(struct mailimap_capability_data * cap_data);
1092
1093
1094
1095/* this is the type of continue request data */
1096
1097enum {
1098 MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */
1099 MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */
1100 MAILIMAP_CONTINUE_REQ_BASE64, /* when data is a base64 response */
1101};
1102
1103/*
1104 mailimap_continue_req is a continue request (a response prefixed by "+")
1105
1106 - type is the type of continue request response
1107 MAILIMAP_CONTINUE_REQ_TEXT (when information data is text),
1108 MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64)
1109
1110 - text is the information of type text in case of text data
1111
1112 - base64 is base64 encoded data in the other case, should be allocated
1113 with malloc()
1114*/
1115
1116struct mailimap_continue_req {
1117 int cr_type;
1118 union {
1119 struct mailimap_resp_text * cr_text; /* can be NULL */
1120 char * cr_base64; /* can be NULL */
1121 } cr_data;
1122};
1123
1124struct mailimap_continue_req *
1125mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text,
1126 char * cr_base64);
1127
1128void mailimap_continue_req_free(struct mailimap_continue_req * cont_req);
1129
1130
1131/*
1132 mailimap_date_time is a date
1133
1134 - day is the day of month (1 to 31)
1135
1136 - month (1 to 12)
1137
1138 - year (4 digits)
1139
1140 - hour (0 to 23)
1141
1142 - min (0 to 59)
1143
1144 - sec (0 to 59)
1145
1146 - zone (this is the decimal value that we can read, for example:
1147 for "-0200", the value is -200)
1148*/
1149
1150struct mailimap_date_time {
1151 int dt_day;
1152 int dt_month;
1153 int dt_year;
1154 int dt_hour;
1155 int dt_min;
1156 int dt_sec;
1157 int dt_zone;
1158};
1159
1160struct mailimap_date_time *
1161mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour,
1162 int dt_min, int dt_sec, int dt_zone);
1163
1164void mailimap_date_time_free(struct mailimap_date_time * date_time);
1165
1166
1167
1168/*
1169 mailimap_envelope is the list of fields that can be parsed by
1170 the IMAP server.
1171
1172 - date is the (non-parsed) content of the "Date" header field,
1173 should be allocated with malloc()
1174
1175 - subject is the subject of the message, should be allocated with
1176 malloc()
1177
1178 - sender is the the parsed content of the "Sender" field
1179
1180 - reply-to is the parsed content of the "Reply-To" field
1181
1182 - to is the parsed content of the "To" field
1183
1184 - cc is the parsed content of the "Cc" field
1185
1186 - bcc is the parsed content of the "Bcc" field
1187
1188 - in_reply_to is the content of the "In-Reply-To" field,
1189 should be allocated with malloc()
1190
1191 - message_id is the content of the "Message-ID" field,
1192 should be allocated with malloc()
1193*/
1194
1195struct mailimap_envelope {
1196 char * env_date; /* can be NULL */
1197 char * env_subject; /* can be NULL */
1198 struct mailimap_env_from * env_from; /* can be NULL */
1199 struct mailimap_env_sender * env_sender; /* can be NULL */
1200 struct mailimap_env_reply_to * env_reply_to; /* can be NULL */
1201 struct mailimap_env_to * env_to; /* can be NULL */
1202 struct mailimap_env_cc * env_cc; /* can be NULL */
1203 struct mailimap_env_bcc * env_bcc; /* can be NULL */
1204 char * env_in_reply_to; /* can be NULL */
1205 char * env_message_id; /* can be NULL */
1206};
1207
1208struct mailimap_envelope *
1209mailimap_envelope_new(char * env_date, char * env_subject,
1210 struct mailimap_env_from * env_from,
1211 struct mailimap_env_sender * env_sender,
1212 struct mailimap_env_reply_to * env_reply_to,
1213 struct mailimap_env_to * env_to,
1214 struct mailimap_env_cc* env_cc,
1215 struct mailimap_env_bcc * env_bcc,
1216 char * env_in_reply_to, char * env_message_id);
1217
1218void mailimap_envelope_free(struct mailimap_envelope * env);
1219
1220
1221
1222/*
1223 mailimap_env_bcc is the parsed "Bcc" field
1224
1225 - list is the list of addresses
1226*/
1227
1228struct mailimap_env_bcc {
1229 clist * bcc_list; /* list of (struct mailimap_address *), != NULL */
1230};
1231
1232struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list);
1233
1234void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc);
1235
1236
1237/*
1238 mailimap_env_cc is the parsed "Cc" field
1239
1240 - list is the list of addresses
1241*/
1242
1243struct mailimap_env_cc {
1244 clist * cc_list; /* list of (struct mailimap_address *), != NULL */
1245};
1246
1247struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list);
1248
1249void mailimap_env_cc_free(struct mailimap_env_cc * env_cc);
1250
1251
1252
1253/*
1254 mailimap_env_from is the parsed "From" field
1255
1256 - list is the list of addresses
1257*/
1258
1259struct mailimap_env_from {
1260 clist * frm_list; /* list of (struct mailimap_address *) */
1261 /* != NULL */
1262};
1263
1264struct mailimap_env_from * mailimap_env_from_new(clist * frm_list);
1265
1266void mailimap_env_from_free(struct mailimap_env_from * env_from);
1267
1268
1269
1270/*
1271 mailimap_env_reply_to is the parsed "Reply-To" field
1272
1273 - list is the list of addresses
1274*/
1275
1276struct mailimap_env_reply_to {
1277 clist * rt_list; /* list of (struct mailimap_address *), != NULL */
1278};
1279
1280struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list);
1281
1282void
1283mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to);
1284
1285
1286
1287/*
1288 mailimap_env_sender is the parsed "Sender" field
1289
1290 - list is the list of addresses
1291*/
1292
1293struct mailimap_env_sender {
1294 clist * snd_list; /* list of (struct mailimap_address *), != NULL */
1295};
1296
1297struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list);
1298
1299void mailimap_env_sender_free(struct mailimap_env_sender * env_sender);
1300
1301
1302
1303/*
1304 mailimap_env_to is the parsed "To" field
1305
1306 - list is the list of addresses
1307*/
1308
1309struct mailimap_env_to {
1310 clist * to_list; /* list of (struct mailimap_address *), != NULL */
1311};
1312
1313struct mailimap_env_to * mailimap_env_to_new(clist * to_list);
1314
1315void mailimap_env_to_free(struct mailimap_env_to * env_to);
1316
1317
1318/* this is the type of flag */
1319
1320enum {
1321 MAILIMAP_FLAG_ANSWERED, /* \Answered flag */
1322 MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */
1323 MAILIMAP_FLAG_DELETED, /* \Deleted flag */
1324 MAILIMAP_FLAG_SEEN, /* \Seen flag */
1325 MAILIMAP_FLAG_DRAFT, /* \Draft flag */
1326 MAILIMAP_FLAG_KEYWORD, /* keyword flag */
1327 MAILIMAP_FLAG_EXTENSION, /* \extension flag */
1328};
1329
1330
1331/*
1332 mailimap_flag is a message flag (that we can associate with a message)
1333
1334 - type is the type of the flag, MAILIMAP_FLAG_XXX
1335
1336 - keyword is the flag when the flag is of keyword type,
1337 should be allocated with malloc()
1338
1339 - extension is the flag when the flag is of extension type, should be
1340 allocated with malloc()
1341*/
1342
1343struct mailimap_flag {
1344 int fl_type;
1345 union {
1346 char * fl_keyword; /* can be NULL */
1347 char * fl_extension; /* can be NULL */
1348 } fl_data;
1349};
1350
1351struct mailimap_flag * mailimap_flag_new(int fl_type,
1352 char * fl_keyword, char * fl_extension);
1353
1354void mailimap_flag_free(struct mailimap_flag * f);
1355
1356
1357
1358
1359/* this is the type of flag */
1360
1361enum {
1362 MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */
1363 MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */
1364 MAILIMAP_FLAG_FETCH_OTHER, /* other type of flag */
1365};
1366
1367/*
1368 mailimap_flag_fetch is a message flag (when we fetch it)
1369
1370 - type is the type of flag fetch
1371
1372 - flag is the flag when this is not a \Recent flag
1373*/
1374
1375struct mailimap_flag_fetch {
1376 int fl_type;
1377 struct mailimap_flag * fl_flag; /* can be NULL */
1378};
1379
1380struct mailimap_flag_fetch *
1381mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag);
1382
1383void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch);
1384
1385
1386
1387
1388/* this is the type of flag */
1389
1390enum {
1391 MAILIMAP_FLAG_PERM_ERROR, /* on parse error */
1392 MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */
1393 MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */
1394};
1395
1396
1397/*
1398 mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response
1399
1400 - type is the type of returned PERMANENTFLAGS, it can be
1401 MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or
1402 MAILIMAP_FLAG_PERM_ALL (new flags can be created)
1403
1404 - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG
1405*/
1406
1407struct mailimap_flag_perm {
1408 int fl_type;
1409 struct mailimap_flag * fl_flag; /* can be NULL */
1410};
1411
1412struct mailimap_flag_perm *
1413mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag);
1414
1415void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm);
1416
1417
1418/*
1419 mailimap_flag_list is a list of flags
1420
1421 - list is a list of flags
1422*/
1423
1424struct mailimap_flag_list {
1425 clist * fl_list; /* list of (struct mailimap_flag *), != NULL */
1426};
1427
1428struct mailimap_flag_list *
1429mailimap_flag_list_new(clist * fl_list);
1430
1431void mailimap_flag_list_free(struct mailimap_flag_list * flag_list);
1432
1433
1434
1435
1436/* this is the type of greeting response */
1437
1438enum {
1439 MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */
1440 MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */
1441 MAILIMAP_GREETING_RESP_COND_BYE, /* when connection is refused */
1442};
1443
1444/*
1445 mailimap_greeting is the response returned on connection
1446
1447 - type is the type of response on connection, either
1448 MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or
1449 MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused
1450*/
1451
1452struct mailimap_greeting {
1453 int gr_type;
1454 union {
1455 struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */
1456 struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */
1457 } gr_data;
1458};
1459
1460struct mailimap_greeting *
1461mailimap_greeting_new(int gr_type,
1462 struct mailimap_resp_cond_auth * gr_auth,
1463 struct mailimap_resp_cond_bye * gr_bye);
1464
1465void mailimap_greeting_free(struct mailimap_greeting * greeting);
1466
1467
1468/*
1469 mailimap_header_list is a list of headers that can be specified when
1470 we want to fetch fields
1471
1472 - list is a list of header names, each header name should be allocated
1473 with malloc()
1474*/
1475
1476struct mailimap_header_list {
1477 clist * hdr_list; /* list of astring (char *), != NULL */
1478};
1479
1480struct mailimap_header_list *
1481mailimap_header_list_new(clist * hdr_list);
1482
1483void
1484mailimap_header_list_free(struct mailimap_header_list * header_list);
1485
1486
1487
1488/* this is the type of mailbox STATUS that can be returned */
1489
1490enum {
1491 MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of
1492 messages */
1493 MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of
1494 recent messages */
1495 MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique
1496 identifier */
1497 MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of
1498 message unique identifiers*/
1499 MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of
1500 unseen messages */
1501};
1502
1503/*
1504 mailimap_status_info is a returned information when a STATUS of
1505 a mailbox is requested
1506
1507 - att is the type of mailbox STATUS, the value can be
1508 MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT,
1509 MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or
1510 MAILIMAP_STATUS_ATT_UNSEEN
1511
1512 - value is the value of the given information
1513*/
1514
1515struct mailimap_status_info {
1516 int st_att;
1517 uint32_t st_value;
1518};
1519
1520struct mailimap_status_info *
1521mailimap_status_info_new(int st_att, uint32_t st_value);
1522
1523void mailimap_status_info_free(struct mailimap_status_info * info);
1524
1525
1526
1527/*
1528 mailimap_mailbox_data_status is the list of information returned
1529 when a STATUS of a mailbox is requested
1530
1531 - mailbox is the name of the mailbox, should be allocated with malloc()
1532
1533 - status_info_list is the list of information returned
1534*/
1535
1536struct mailimap_mailbox_data_status {
1537 char * st_mailbox;
1538 clist * st_info_list; /* list of (struct mailimap_status_info *) */
1539 /* can be NULL */
1540};
1541
1542struct mailimap_mailbox_data_status *
1543mailimap_mailbox_data_status_new(char * st_mailbox,
1544 clist * st_info_list);
1545
1546void
1547mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info);
1548
1549
1550
1551/* this is the type of mailbox information that is returned */
1552
1553enum {
1554 MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */
1555 MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */
1556 MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes
1557 returned on LIST command*/
1558 MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of
1559 subscribed mailboxes returned on LSUB
1560 command */
1561 MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or
1562 unique identifiers returned
1563 on a SEARCH command*/
1564 MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned
1565 on a STATUS command */
1566 MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the
1567 mailbox */
1568 MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages
1569 in the mailbox */
1570};
1571
1572/*
1573 mailimap_mailbox_data is an information related to a mailbox
1574
1575 - type is the type of mailbox_data that is filled, the value of this field
1576 can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST,
1577 MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH,
1578 MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS
1579 or MAILIMAP_MAILBOX_DATA_RECENT.
1580
1581 - flags is the flags that are applicable to the mailbox when
1582 type is MAILIMAP_MAILBOX_DATA_FLAGS
1583
1584 - list is a mailbox in the list of mailboxes returned on LIST command
1585 when type is MAILIMAP_MAILBOX_DATA_LIST
1586
1587 - lsub is a mailbox in the list of subscribed mailboxes returned on
1588 LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB
1589
1590 - search is a list of messages numbers or unique identifiers returned
1591 on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element
1592 should be allocated with malloc()
1593
1594 - status is a list of information returned on STATUS command when
1595 type is MAILIMAP_MAILBOX_DATA_STATUS
1596
1597 - exists is the number of messages in the mailbox when type
1598 is MAILIMAP_MAILBOX_DATA_EXISTS
1599
1600 - recent is the number of recent messages in the mailbox when type
1601 is MAILIMAP_MAILBOX_DATA_RECENT
1602*/
1603
1604struct mailimap_mailbox_data {
1605 int mbd_type;
1606 union {
1607 struct mailimap_flag_list * mbd_flags; /* can be NULL */
1608 struct mailimap_mailbox_list * mbd_list; /* can be NULL */
1609 struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */
1610 clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */
1611 struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */
1612 uint32_t mbd_exists;
1613 uint32_t mbd_recent;
1614 } mbd_data;
1615};
1616
1617struct mailimap_mailbox_data *
1618mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags,
1619 struct mailimap_mailbox_list * mbd_list,
1620 struct mailimap_mailbox_list * mbd_lsub,
1621 clist * mbd_search,
1622 struct mailimap_mailbox_data_status * mbd_status,
1623 uint32_t mbd_exists,
1624 uint32_t mbd_recent);
1625
1626void
1627mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data);
1628
1629
1630
1631/* this is the type of mailbox flags */
1632
1633enum {
1634 MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in
1635 {\NoSelect, \Marked, \Unmarked} */
1636 MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG, /* mailbox other flag - mailbox flag
1637 other than \NoSelect \Marked and
1638 \Unmarked) */
1639};
1640
1641/* this is a single flag type */
1642
1643enum {
1644 MAILIMAP_MBX_LIST_SFLAG_ERROR,
1645 MAILIMAP_MBX_LIST_SFLAG_MARKED,
1646 MAILIMAP_MBX_LIST_SFLAG_NOSELECT,
1647 MAILIMAP_MBX_LIST_SFLAG_UNMARKED
1648};
1649
1650/*
1651 mailimap_mbx_list_flags is a mailbox flag
1652
1653 - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG,
1654 or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG.
1655
1656 - oflags is a list of "mailbox other flag"
1657
1658 - sflag is a mailbox single flag
1659*/
1660
1661struct mailimap_mbx_list_flags {
1662 int mbf_type;
1663 clist * mbf_oflags; /* list of
1664 (struct mailimap_mbx_list_oflag *), != NULL */
1665 int mbf_sflag;
1666};
1667
1668struct mailimap_mbx_list_flags *
1669mailimap_mbx_list_flags_new(int mbf_type,
1670 clist * mbf_oflags, int mbf_sflag);
1671
1672void
1673mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags);
1674
1675
1676
1677/* this is the type of the mailbox other flag */
1678
1679enum {
1680 MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */
1681 MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */
1682 MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */
1683};
1684
1685/*
1686 mailimap_mbx_list_oflag is a mailbox other flag
1687
1688 - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is
1689 a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT
1690
1691 - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is
1692 an extension flag, should be allocated with malloc()
1693*/
1694
1695struct mailimap_mbx_list_oflag {
1696 int of_type;
1697 char * of_flag_ext; /* can be NULL */
1698};
1699
1700struct mailimap_mbx_list_oflag *
1701mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext);
1702
1703void
1704mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag);
1705
1706
1707
1708/*
1709 mailimap_mailbox_list is a list of mailbox flags
1710
1711 - mb_flag is a list of mailbox flags
1712
1713 - delimiter is the delimiter of the mailbox path
1714
1715 - mb is the name of the mailbox, should be allocated with malloc()
1716*/
1717
1718struct mailimap_mailbox_list {
1719 struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */
1720 char mb_delimiter;
1721 char * mb_name; /* != NULL */
1722};
1723
1724struct mailimap_mailbox_list *
1725mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags,
1726 char mb_delimiter, char * mb_name);
1727
1728void
1729mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list);
1730
1731
1732
1733/* this is the MIME type */
1734
1735enum {
1736 MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */
1737 MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */
1738 MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */
1739 MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */
1740 MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */
1741 MAILIMAP_MEDIA_BASIC_OTHER, /* for all other cases */
1742};
1743
1744
1745/*
1746 mailimap_media_basic is the MIME type
1747
1748 - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO,
1749 MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE,
1750 MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER
1751
1752 - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should
1753 be allocated with malloc()
1754
1755 - subtype is the subtype of the MIME type, for example, this is
1756 "data" in "application/data", should be allocated with malloc()
1757*/
1758
1759struct mailimap_media_basic {
1760 int med_type;
1761 char * med_basic_type; /* can be NULL */
1762 char * med_subtype; /* != NULL */
1763};
1764
1765struct mailimap_media_basic *
1766mailimap_media_basic_new(int med_type,
1767 char * med_basic_type, char * med_subtype);
1768
1769void
1770mailimap_media_basic_free(struct mailimap_media_basic * media_basic);
1771
1772
1773
1774/* this is the type of message data */
1775
1776enum {
1777 MAILIMAP_MESSAGE_DATA_ERROR,
1778 MAILIMAP_MESSAGE_DATA_EXPUNGE,
1779 MAILIMAP_MESSAGE_DATA_FETCH
1780};
1781
1782/*
1783 mailimap_message_data is an information related to a message
1784
1785 - number is the number or the unique identifier of the message
1786
1787 - type is the type of information, this value can be
1788 MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH
1789
1790 - msg_att is the message data
1791*/
1792
1793struct mailimap_message_data {
1794 uint32_t mdt_number;
1795 int mdt_type;
1796 struct mailimap_msg_att * mdt_msg_att; /* can be NULL */
1797 /* if type = EXPUNGE, can be NULL */
1798};
1799
1800struct mailimap_message_data *
1801mailimap_message_data_new(uint32_t mdt_number, int mdt_type,
1802 struct mailimap_msg_att * mdt_msg_att);
1803
1804void
1805mailimap_message_data_free(struct mailimap_message_data * msg_data);
1806
1807
1808
1809/* this the type of the message attributes */
1810
1811enum {
1812 MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */
1813 MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */
1814 MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes
1815 (message content) */
1816};
1817
1818/*
1819 mailimap_msg_att_item is a message attribute
1820
1821 - type is the type of message attribute, the value can be
1822 MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC
1823
1824 - msg_att_dyn is a dynamic message attribute when type is
1825 MAILIMAP_MSG_ATT_ITEM_DYNAMIC
1826
1827 - msg_att_static is a static message attribute when type is
1828 MAILIMAP_MSG_ATT_ITEM_STATIC
1829*/
1830
1831struct mailimap_msg_att_item {
1832 int att_type;
1833 union {
1834 struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */
1835 struct mailimap_msg_att_static * att_static; /* can be NULL */
1836 } att_data;
1837};
1838
1839struct mailimap_msg_att_item *
1840mailimap_msg_att_item_new(int att_type,
1841 struct mailimap_msg_att_dynamic * att_dyn,
1842 struct mailimap_msg_att_static * att_static);
1843
1844void
1845mailimap_msg_att_item_free(struct mailimap_msg_att_item * item);
1846
1847
1848/*
1849 mailimap_msg_att is a list of attributes
1850
1851 - list is a list of message attributes
1852
1853 - number is the message number or unique identifier, this field
1854 has been added for implementation purpose
1855*/
1856
1857struct mailimap_msg_att {
1858 clist * att_list; /* list of (struct mailimap_msg_att_item *) */
1859 /* != NULL */
1860 uint32_t att_number; /* extra field to store the message number,
1861 used for mailimap */
1862};
1863
1864struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list);
1865
1866void mailimap_msg_att_free(struct mailimap_msg_att * msg_att);
1867
1868
1869/*
1870 mailimap_msg_att_dynamic is a dynamic message attribute
1871
1872 - list is a list of flags (that have been fetched)
1873*/
1874
1875struct mailimap_msg_att_dynamic {
1876 clist * att_list; /* list of (struct mailimap_flag_fetch *) */
1877 /* can be NULL */
1878};
1879
1880struct mailimap_msg_att_dynamic *
1881mailimap_msg_att_dynamic_new(clist * att_list);
1882
1883void
1884mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn);
1885
1886
1887
1888/*
1889 mailimap_msg_att_body_section is a MIME part content
1890
1891 - section is the location of the MIME part in the message
1892
1893 - origin_octet is the offset of the requested part of the MIME part
1894
1895 - body_part is the content or partial content of the MIME part,
1896 should be allocated through a MMAPString
1897
1898 - length is the size of the content
1899*/
1900
1901struct mailimap_msg_att_body_section {
1902 struct mailimap_section * sec_section; /* != NULL */
1903 uint32_t sec_origin_octet;
1904 char * sec_body_part; /* can be NULL */
1905 size_t sec_length;
1906};
1907
1908struct mailimap_msg_att_body_section *
1909mailimap_msg_att_body_section_new(struct mailimap_section * section,
1910 uint32_t sec_origin_octet,
1911 char * sec_body_part,
1912 size_t sec_length);
1913
1914void
1915mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section *
1916 msg_att_body_section);
1917
1918
1919
1920/*
1921 this is the type of static message attribute
1922*/
1923
1924enum {
1925 MAILIMAP_MSG_ATT_ERROR, /* on parse error */
1926 MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be
1927 parsed by the server */
1928 MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept
1929 by the server */
1930 MAILIMAP_MSG_ATT_RFC822, /* this is the message content
1931 (header and body) */
1932 MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */
1933 MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */
1934 MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */
1935 MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of
1936 the message */
1937 MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the
1938 message with additional information */
1939 MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */
1940 MAILIMAP_MSG_ATT_UID, /* this is the message unique identifier */
1941};
1942
1943/*
1944 mailimap_msg_att_static is a given part of the message
1945
1946 - type is the type of the static message attribute, the value can be
1947 MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE,
1948 MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER,
1949 MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE,
1950 MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE,
1951 MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID
1952
1953 - env is the headers parsed by the server if type is
1954 MAILIMAP_MSG_ATT_ENVELOPE
1955
1956 - internal_date is the date of message kept by the server if type is
1957 MAILIMAP_MSG_ATT_INTERNALDATE
1958
1959 - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822,
1960 should be allocated through a MMAPString
1961
1962 - rfc822_header is the message header if type is
1963 MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString
1964
1965 - rfc822_text is the message text part if type is
1966 MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString
1967
1968 - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE
1969
1970 - body is the MIME description of the message
1971
1972 - bodystructure is the MIME description of the message with additional
1973 information
1974
1975 - body_section is a MIME part content
1976
1977 - uid is a unique message identifier
1978*/
1979
1980struct mailimap_msg_att_static {
1981 int att_type;
1982 union {
1983 struct mailimap_envelope * att_env; /* can be NULL */
1984 struct mailimap_date_time * att_internal_date; /* can be NULL */
1985 struct {
1986 char * att_content; /* can be NULL */
1987 size_t att_length;
1988 } att_rfc822;
1989 struct {
1990 char * att_content; /* can be NULL */
1991 size_t att_length;
1992 } att_rfc822_header;
1993 struct {
1994 char * att_content; /* can be NULL */
1995 size_t att_length;
1996 } att_rfc822_text;
1997 uint32_t att_rfc822_size;
1998 struct mailimap_body * att_bodystructure; /* can be NULL */
1999 struct mailimap_body * att_body; /* can be NULL */
2000 struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */
2001 uint32_t att_uid;
2002 } att_data;
2003};
2004
2005struct mailimap_msg_att_static *
2006mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env,
2007 struct mailimap_date_time * att_internal_date,
2008 char * att_rfc822,
2009 char * att_rfc822_header,
2010 char * att_rfc822_text,
2011 size_t att_length,
2012 uint32_t att_rfc822_size,
2013 struct mailimap_body * att_bodystructure,
2014 struct mailimap_body * att_body,
2015 struct mailimap_msg_att_body_section * att_body_section,
2016 uint32_t att_uid);
2017
2018void
2019mailimap_msg_att_static_free(struct mailimap_msg_att_static * item);
2020
2021
2022
2023/* this is the type of a response element */
2024
2025enum {
2026 MAILIMAP_RESP_ERROR, /* on parse error */
2027 MAILIMAP_RESP_CONT_REQ, /* continuation request */
2028 MAILIMAP_RESP_RESP_DATA, /* response data */
2029};
2030
2031/*
2032 mailimap_cont_req_or_resp_data is a response element
2033
2034 - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ
2035 or MAILIMAP_RESP_RESP_DATA
2036
2037 - cont_req is a continuation request
2038
2039 - resp_data is a reponse data
2040*/
2041
2042struct mailimap_cont_req_or_resp_data {
2043 int rsp_type;
2044 union {
2045 struct mailimap_continue_req * rsp_cont_req; /* can be NULL */
2046 struct mailimap_response_data * rsp_resp_data; /* can be NULL */
2047 } rsp_data;
2048};
2049
2050struct mailimap_cont_req_or_resp_data *
2051mailimap_cont_req_or_resp_data_new(int rsp_type,
2052 struct mailimap_continue_req * rsp_cont_req,
2053 struct mailimap_response_data * rsp_resp_data);
2054
2055void
2056mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data *
2057 cont_req_or_resp_data);
2058
2059
2060/*
2061 mailimap_response is a list of response elements
2062
2063 - cont_req_or_resp_data_list is a list of response elements
2064
2065 - resp_done is an ending response element
2066*/
2067
2068struct mailimap_response {
2069 clist * rsp_cont_req_or_resp_data_list;
2070 /* list of (struct mailiap_cont_req_or_resp_data *) */
2071 /* can be NULL */
2072 struct mailimap_response_done * rsp_resp_done; /* != NULL */
2073};
2074
2075struct mailimap_response *
2076mailimap_response_new(clist * rsp_cont_req_or_resp_data_list,
2077 struct mailimap_response_done * rsp_resp_done);
2078
2079void
2080mailimap_response_free(struct mailimap_response * resp);
2081
2082
2083
2084/* this is the type of an untagged response */
2085
2086enum {
2087 MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */
2088 MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */
2089 MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about
2090 to close the connection) */
2091 MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */
2092 MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */
2093 MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */
2094};
2095
2096/*
2097 mailimap_reponse_data is an untagged response
2098
2099 - type is the type of the untagged response, it can be
2100 MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE,
2101 MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA
2102 or MAILIMAP_RESP_DATA_CAPABILITY_DATA
2103
2104 - cond_state is a condition state response
2105
2106 - bye is a BYE response (server is about to close the connection)
2107
2108 - mailbox_data is a response related to a mailbox
2109
2110 - message_data is a response related to a message
2111
2112 - capability is information about capabilities
2113*/
2114
2115struct mailimap_response_data {
2116 int rsp_type;
2117 union {
2118 struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */
2119 struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */
2120 struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */
2121 struct mailimap_message_data * rsp_message_data; /* can be NULL */
2122 struct mailimap_capability_data * rsp_capability_data; /* can be NULL */
2123 } rsp_data;
2124};
2125
2126struct mailimap_response_data *
2127mailimap_response_data_new(int rsp_type,
2128 struct mailimap_resp_cond_state * rsp_cond_state,
2129 struct mailimap_resp_cond_bye * rsp_bye,
2130 struct mailimap_mailbox_data * rsp_mailbox_data,
2131 struct mailimap_message_data * rsp_message_data,
2132 struct mailimap_capability_data * rsp_capability_data);
2133
2134void
2135mailimap_response_data_free(struct mailimap_response_data * resp_data);
2136
2137
2138
2139/* this is the type of an ending response */
2140
2141enum {
2142 MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */
2143 MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */
2144 MAILIMAP_RESP_DONE_TYPE_FATAL, /* fatal error response */
2145};
2146
2147/*
2148 mailimap_response_done is an ending response
2149
2150 - type is the type of the ending response
2151
2152 - tagged is a tagged response
2153
2154 - fatal is a fatal error response
2155*/
2156
2157struct mailimap_response_done {
2158 int rsp_type;
2159 union {
2160 struct mailimap_response_tagged * rsp_tagged; /* can be NULL */
2161 struct mailimap_response_fatal * rsp_fatal; /* can be NULL */
2162 } rsp_data;
2163};
2164
2165struct mailimap_response_done *
2166mailimap_response_done_new(int rsp_type,
2167 struct mailimap_response_tagged * rsp_tagged,
2168 struct mailimap_response_fatal * rsp_fatal);
2169
2170void mailimap_response_done_free(struct mailimap_response_done *
2171 resp_done);
2172
2173
2174/*
2175 mailimap_response_fatal is a fatal error response
2176
2177 - bye is a BYE response text
2178*/
2179
2180struct mailimap_response_fatal {
2181 struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */
2182};
2183
2184struct mailimap_response_fatal *
2185mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye);
2186
2187void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal);
2188
2189
2190
2191/*
2192 mailimap_response_tagged is a tagged response
2193
2194 - tag is the sent tag, should be allocated with malloc()
2195
2196 - cond_state is a condition state response
2197*/
2198
2199struct mailimap_response_tagged {
2200 char * rsp_tag; /* != NULL */
2201 struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */
2202};
2203
2204struct mailimap_response_tagged *
2205mailimap_response_tagged_new(char * rsp_tag,
2206 struct mailimap_resp_cond_state * rsp_cond_state);
2207
2208void
2209mailimap_response_tagged_free(struct mailimap_response_tagged * tagged);
2210
2211
2212/* this is the type of an authentication condition response */
2213
2214enum {
2215 MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */
2216 MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */
2217 MAILIMAP_RESP_COND_AUTH_PREAUTH, /* authentication is not needed */
2218};
2219
2220/*
2221 mailimap_resp_cond_auth is an authentication condition response
2222
2223 - type is the type of the authentication condition response,
2224 the value can be MAILIMAP_RESP_COND_AUTH_OK or
2225 MAILIMAP_RESP_COND_AUTH_PREAUTH
2226
2227 - text is a text response
2228*/
2229
2230struct mailimap_resp_cond_auth {
2231 int rsp_type;
2232 struct mailimap_resp_text * rsp_text; /* != NULL */
2233};
2234
2235struct mailimap_resp_cond_auth *
2236mailimap_resp_cond_auth_new(int rsp_type,
2237 struct mailimap_resp_text * rsp_text);
2238
2239void
2240mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth);
2241
2242
2243
2244/*
2245 mailimap_resp_cond_bye is a BYE response
2246
2247 - text is a text response
2248*/
2249
2250struct mailimap_resp_cond_bye {
2251 struct mailimap_resp_text * rsp_text; /* != NULL */
2252};
2253
2254struct mailimap_resp_cond_bye *
2255mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text);
2256
2257void
2258mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye);
2259
2260
2261
2262/* this is the type of a condition state response */
2263
2264enum {
2265 MAILIMAP_RESP_COND_STATE_OK,
2266 MAILIMAP_RESP_COND_STATE_NO,
2267 MAILIMAP_RESP_COND_STATE_BAD
2268};
2269
2270/*
2271 mailimap_resp_cond_state is a condition state reponse
2272
2273 - type is the type of the condition state response
2274
2275 - text is a text response
2276*/
2277
2278struct mailimap_resp_cond_state {
2279 int rsp_type;
2280 struct mailimap_resp_text * rsp_text; /* can be NULL */
2281};
2282
2283struct mailimap_resp_cond_state *
2284mailimap_resp_cond_state_new(int rsp_type,
2285 struct mailimap_resp_text * rsp_text);
2286
2287void
2288mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state);
2289
2290
2291
2292/*
2293 mailimap_resp_text is a text response
2294
2295 - resp_code is a response code
2296
2297 - text is a human readable text, should be allocated with malloc()
2298*/
2299
2300struct mailimap_resp_text {
2301 struct mailimap_resp_text_code * rsp_code; /* can be NULL */
2302 char * rsp_text; /* can be NULL */
2303};
2304
2305struct mailimap_resp_text *
2306mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code,
2307 char * rsp_text);
2308
2309void mailimap_resp_text_free(struct mailimap_resp_text * resp_text);
2310
2311
2312
2313/* this is the type of the response code */
2314
2315enum {
2316 MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */
2317 MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */
2318 MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */
2319 MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */
2320 MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */
2321 MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */
2322 MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */
2323 MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */
2324 MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */
2325 MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */
2326 MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */
2327 MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */
2328};
2329
2330/*
2331 mailimap_resp_text_code is a response code
2332
2333 - type is the type of the response code, the value can be
2334 MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET,
2335 MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE,
2336 MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY,
2337 MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE,
2338 MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY,
2339 MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER
2340
2341 - badcharset is a list of charsets if type
2342 is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be
2343 allocated with malloc()
2344
2345 - cap_data is a list of capabilities
2346
2347 - perm_flags is a list of flags, this is the flags that can be changed
2348 permanently on the messages of the mailbox.
2349
2350 - uidnext is the next unique identifier of a message
2351
2352 - uidvalidity is the unique identifier validity value
2353
2354 - first_unseen is the number of the first message without the \Seen flag
2355
2356 - atom is a keyword for an extension response code, should be allocated
2357 with malloc()
2358
2359 - atom_value is the data related with the extension response code,
2360 should be allocated with malloc()
2361*/
2362
2363struct mailimap_resp_text_code {
2364 int rc_type;
2365 union {
2366 clist * rc_badcharset; /* list of astring (char *) */
2367 /* can be NULL */
2368 struct mailimap_capability_data * rc_cap_data; /* != NULL */
2369 clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */
2370 /* can be NULL */
2371 uint32_t rc_uidnext;
2372 uint32_t rc_uidvalidity;
2373 uint32_t rc_first_unseen;
2374 struct {
2375 char * atom_name; /* can be NULL */
2376 char * atom_value; /* can be NULL */
2377 } rc_atom;
2378 } rc_data;
2379};
2380
2381struct mailimap_resp_text_code *
2382mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset,
2383 struct mailimap_capability_data * rc_cap_data,
2384 clist * rc_perm_flags,
2385 uint32_t rc_uidnext, uint32_t rc_uidvalidity,
2386 uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value);
2387
2388void
2389mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code);
2390
2391
2392/*
2393 mailimap_section is a MIME part section identifier
2394
2395 section_spec is the MIME section identifier
2396*/
2397
2398struct mailimap_section {
2399 struct mailimap_section_spec * sec_spec; /* can be NULL */
2400};
2401
2402struct mailimap_section *
2403mailimap_section_new(struct mailimap_section_spec * sec_spec);
2404
2405void mailimap_section_free(struct mailimap_section * section);
2406
2407
2408/* this is the type of the message/rfc822 part description */
2409
2410enum {
2411 MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the
2412 message */
2413 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the
2414 message */
2415 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the
2416 message except the given */
2417 MAILIMAP_SECTION_MSGTEXT_TEXT, /* text part */
2418};
2419
2420/*
2421 mailimap_section_msgtext is a message/rfc822 part description
2422
2423 - type is the type of the content part and the value can be
2424 MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS,
2425 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT
2426 or MAILIMAP_SECTION_MSGTEXT_TEXT
2427
2428 - header_list is the list of headers when type is
2429 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or
2430 MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT
2431*/
2432
2433struct mailimap_section_msgtext {
2434 int sec_type;
2435 struct mailimap_header_list * sec_header_list; /* can be NULL */
2436};
2437
2438struct mailimap_section_msgtext *
2439mailimap_section_msgtext_new(int sec_type,
2440 struct mailimap_header_list * sec_header_list);
2441
2442void
2443mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext);
2444
2445
2446
2447/*
2448 mailimap_section_part is the MIME part location in a message
2449
2450 - section_id is a list of number index of the sub-part in the mail structure,
2451 each element should be allocated with malloc()
2452
2453*/
2454
2455struct mailimap_section_part {
2456 clist * sec_id; /* list of nz-number (uint32_t *) */
2457 /* != NULL */
2458};
2459
2460struct mailimap_section_part *
2461mailimap_section_part_new(clist * sec_id);
2462
2463void
2464mailimap_section_part_free(struct mailimap_section_part * section_part);
2465
2466
2467
2468/* this is the type of section specification */
2469
2470enum {
2471 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root
2472 MIME message/rfc822 part */
2473 MAILIMAP_SECTION_SPEC_SECTION_PART, /* location of the MIME part
2474 in the message */
2475};
2476
2477/*
2478 mailimap_section_spec is a section specification
2479
2480 - type is the type of the section specification, the value can be
2481 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or
2482 MAILIMAP_SECTION_SPEC_SECTION_PART
2483
2484 - section_msgtext is a message/rfc822 part description if type is
2485 MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT
2486
2487 - section_part is a body part location in the message if type is
2488 MAILIMAP_SECTION_SPEC_SECTION_PART
2489
2490 - section_text is a body part location for a given MIME part,
2491 this can be NULL if the body of the part is requested (and not
2492 the MIME header).
2493*/
2494
2495struct mailimap_section_spec {
2496 int sec_type;
2497 union {
2498 struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */
2499 struct mailimap_section_part * sec_part; /* can be NULL */
2500 } sec_data;
2501 struct mailimap_section_text * sec_text; /* can be NULL */
2502};
2503
2504struct mailimap_section_spec *
2505mailimap_section_spec_new(int sec_type,
2506 struct mailimap_section_msgtext * sec_msgtext,
2507 struct mailimap_section_part * sec_part,
2508 struct mailimap_section_text * sec_text);
2509
2510void
2511mailimap_section_spec_free(struct mailimap_section_spec * section_spec);
2512
2513
2514
2515/* this is the type of body part location for a given MIME part */
2516
2517enum {
2518 MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/
2519 MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is
2520 message/rfc822, headers or text
2521 can be requested */
2522 MAILIMAP_SECTION_TEXT_MIME, /* for all MIME types,
2523 MIME headers can be requested */
2524};
2525
2526/*
2527 mailimap_section_text is the body part location for a given MIME part
2528
2529 - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or
2530 MAILIMAP_SECTION_TEXT_MIME
2531
2532 - section_msgtext is the part of the MIME part when MIME type is
2533 message/rfc822 than can be requested, when type is
2534 MAILIMAP_TEXT_SECTION_MSGTEXT
2535*/
2536
2537struct mailimap_section_text {
2538 int sec_type;
2539 struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */
2540};
2541
2542struct mailimap_section_text *
2543mailimap_section_text_new(int sec_type,
2544 struct mailimap_section_msgtext * sec_msgtext);
2545
2546void
2547mailimap_section_text_free(struct mailimap_section_text * section_text);
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558/* ************************************************************************* */
2559/* the following part concerns only the IMAP command that are sent */
2560
2561
2562/*
2563 mailimap_set_item is a message set
2564
2565 - first is the first message of the set
2566 - last is the last message of the set
2567
2568 this can be message numbers of message unique identifiers
2569*/
2570
2571struct mailimap_set_item {
2572 uint32_t set_first;
2573 uint32_t set_last;
2574};
2575
2576struct mailimap_set_item *
2577mailimap_set_item_new(uint32_t set_first, uint32_t set_last);
2578
2579void mailimap_set_item_free(struct mailimap_set_item * set_item);
2580
2581
2582
2583/*
2584 set is a list of message sets
2585
2586 - list is a list of message sets
2587*/
2588
2589struct mailimap_set {
2590 clist * set_list; /* list of (struct mailimap_set_item *) */
2591};
2592
2593struct mailimap_set * mailimap_set_new(clist * list);
2594
2595void mailimap_set_free(struct mailimap_set * set);
2596
2597
2598/*
2599 mailimap_date is a date
2600
2601 - day is the day in the month (1 to 31)
2602
2603 - month (1 to 12)
2604
2605 - year (4 digits)
2606*/
2607
2608struct mailimap_date {
2609 int dt_day;
2610 int dt_month;
2611 int dt_year;
2612};
2613
2614struct mailimap_date *
2615mailimap_date_new(int dt_day, int dt_month, int dt_year);
2616
2617void mailimap_date_free(struct mailimap_date * date);
2618
2619
2620
2621
2622/* this is the type of fetch attribute for a given message */
2623
2624enum {
2625 MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by
2626 the IMAP server */
2627 MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */
2628 MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message
2629 kept by the server */
2630 MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */
2631 MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */
2632 MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */
2633 MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */
2634 MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */
2635 MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with
2636 additional information */
2637 MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */
2638 MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */
2639 MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without
2640 marking the message as read */
2641};
2642
2643
2644/*
2645 mailimap_fetch_att is the description of the fetch attribute
2646
2647 - type is the type of fetch attribute, the value can be
2648 MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS,
2649 MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822,
2650 MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE,
2651 MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY,
2652 MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID,
2653 MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION
2654
2655 - section is the location of the part to fetch if type is
2656 MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION
2657
2658 - offset is the first byte to fetch in the given part
2659
2660 - size is the maximum size of the part to fetch
2661*/
2662
2663struct mailimap_fetch_att {
2664 int att_type;
2665 struct mailimap_section * att_section;
2666 uint32_t att_offset;
2667 uint32_t att_size;
2668};
2669
2670struct mailimap_fetch_att *
2671mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section,
2672 uint32_t att_offset, uint32_t att_size);
2673
2674
2675void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att);
2676
2677
2678/* this is the type of a FETCH operation */
2679
2680enum {
2681 MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE
2682 RFC822.SIZE ENVELOPE) */
2683 MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE
2684 RFC822.SIZE ENVELOPE BODY) */
2685 MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE
2686 RFC822.SIZE) */
2687 MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch
2688 attribute */
2689 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, /* when there is a list of fetch
2690 attributes */
2691};
2692
2693/*
2694 mailimap_fetch_type is the description of the FETCH operation
2695
2696 - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL,
2697 MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or
2698 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST
2699
2700 - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT
2701
2702 - fetch_att_list is a list of fetch attributes if type is
2703 MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST
2704*/
2705
2706struct mailimap_fetch_type {
2707 int ft_type;
2708 union {
2709 struct mailimap_fetch_att * ft_fetch_att;
2710 clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */
2711 } ft_data;
2712};
2713
2714struct mailimap_fetch_type *
2715mailimap_fetch_type_new(int ft_type,
2716 struct mailimap_fetch_att * ft_fetch_att,
2717 clist * ft_fetch_att_list);
2718
2719
2720void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type);
2721
2722
2723
2724/*
2725 mailimap_store_att_flags is the description of the STORE operation
2726 (change flags of a message)
2727
2728 - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag)
2729
2730 - silent has a value of 1 if the flags are changed with no server
2731 response
2732
2733 - flag_list is the list of flags to change
2734*/
2735
2736struct mailimap_store_att_flags {
2737 int fl_sign;
2738 int fl_silent;
2739 struct mailimap_flag_list * fl_flag_list;
2740};
2741
2742struct mailimap_store_att_flags *
2743mailimap_store_att_flags_new(int fl_sign, int fl_silent,
2744 struct mailimap_flag_list * fl_flag_list);
2745
2746void mailimap_store_att_flags_free(struct mailimap_store_att_flags *
2747 store_att_flags);
2748
2749
2750
2751/* this is the condition of the SEARCH operation */
2752
2753enum {
2754 MAILIMAP_SEARCH_KEY_ALL, /* all messages */
2755 MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */
2756 MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the
2757 given string */
2758 MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier
2759 than the specified date */
2760 MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string
2761 (in header and text parts) */
2762 MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the
2763 given string */
2764 MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */
2765 MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */
2766 MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the
2767 given string */
2768 MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */
2769 MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not
2770 the \Seen flag */
2771 MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the
2772 \Recent flag set */
2773 MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the
2774 specified date */
2775 MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */
2776 MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */
2777 MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later
2778 than specified date */
2779 MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the
2780 given string */
2781 MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the
2782 given string */
2783 MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the
2784 given string */
2785 MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */
2786 MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */
2787 MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */
2788 MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */
2789 MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */
2790 MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */
2791 MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field
2792 contains the given string */
2793 MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then
2794 the given size */
2795 MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */
2796 MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */
2797 MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header
2798 is earlier than the specified date */
2799 MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header
2800 is the specified date */
2801 MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header
2802 is later than specified date */
2803 MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than
2804 the given size */
2805 MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are
2806 in the given range */
2807 MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */
2808 MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique
2809 identifiers in case of UID SEARCH) are
2810 in the given range */
2811 MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the
2812 conditions is AND */
2813};
2814
2815/*
2816 mailimap_search_key is the condition on the messages to return
2817
2818 - type is the type of the condition
2819
2820 - bcc is the text to search in the Bcc field when type is
2821 MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc()
2822
2823 - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE
2824
2825 - body is the text to search in the message when type is
2826 MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc()
2827
2828 - cc is the text to search in the Cc field when type is
2829 MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc()
2830
2831 - from is the text to search in the From field when type is
2832 MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc()
2833
2834 - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD,
2835 should be allocated with malloc()
2836
2837 - on is a date when type is MAILIMAP_SEARCH_KEY_ON
2838
2839 - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE
2840
2841 - subject is the text to search in the Subject field when type is
2842 MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc()
2843
2844 - text is the text to search in the text part of the message when
2845 type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc()
2846
2847 - to is the text to search in the To field when type is
2848 MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc()
2849
2850 - unkeyword is the keyword flag name when type is
2851 MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc()
2852
2853 - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER,
2854 should be allocated with malloc()
2855
2856 - header_value is the text to search in the given header when type is
2857 MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc()
2858
2859 - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER
2860
2861 - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT
2862
2863 - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR
2864
2865 - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR
2866
2867 - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE
2868
2869 - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON
2870
2871 - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE
2872
2873 - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER
2874
2875 - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID
2876
2877 - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET
2878
2879 - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE
2880*/
2881
2882struct mailimap_search_key {
2883 int sk_type;
2884 union {
2885 char * sk_bcc;
2886 struct mailimap_date * sk_before;
2887 char * sk_body;
2888 char * sk_cc;
2889 char * sk_from;
2890 char * sk_keyword;
2891 struct mailimap_date * sk_on;
2892 struct mailimap_date * sk_since;
2893 char * sk_subject;
2894 char * sk_text;
2895 char * sk_to;
2896 char * sk_unkeyword;
2897 struct {
2898 char * sk_header_name;
2899 char * sk_header_value;
2900 } sk_header;
2901 uint32_t sk_larger;
2902 struct mailimap_search_key * sk_not;
2903 struct {
2904 struct mailimap_search_key * sk_or1;
2905 struct mailimap_search_key * sk_or2;
2906 } sk_or;
2907 struct mailimap_date * sk_sentbefore;
2908 struct mailimap_date * sk_senton;
2909 struct mailimap_date * sk_sentsince;
2910 uint32_t sk_smaller;
2911 struct mailimap_set * sk_uid;
2912 struct mailimap_set * sk_set;
2913 clist * sk_multiple; /* list of (struct mailimap_search_key *) */
2914 } sk_data;
2915};
2916
2917struct mailimap_search_key *
2918mailimap_search_key_new(int sk_type,
2919 char * sk_bcc, struct mailimap_date * sk_before, char * sk_body,
2920 char * sk_cc, char * sk_from, char * sk_keyword,
2921 struct mailimap_date * sk_on, struct mailimap_date * sk_since,
2922 char * sk_subject, char * sk_text, char * sk_to,
2923 char * sk_unkeyword, char * sk_header_name,
2924 char * sk_header_value, uint32_t sk_larger,
2925 struct mailimap_search_key * sk_not,
2926 struct mailimap_search_key * sk_or1,
2927 struct mailimap_search_key * sk_or2,
2928 struct mailimap_date * sk_sentbefore,
2929 struct mailimap_date * sk_senton,
2930 struct mailimap_date * sk_sentsince,
2931 uint32_t sk_smaller, struct mailimap_set * sk_uid,
2932 struct mailimap_set * sk_set, clist * sk_multiple);
2933
2934
2935void mailimap_search_key_free(struct mailimap_search_key * key);
2936
2937
2938/*
2939 mailimap_status_att_list is a list of mailbox STATUS request type
2940
2941 - list is a list of mailbox STATUS request type
2942 (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES,
2943 MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT,
2944 MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN),
2945 each element should be allocated with malloc()
2946*/
2947
2948struct mailimap_status_att_list {
2949 clist * att_list; /* list of (uint32_t *) */
2950};
2951
2952struct mailimap_status_att_list *
2953mailimap_status_att_list_new(clist * att_list);
2954
2955void mailimap_status_att_list_free(struct mailimap_status_att_list *
2956 status_att_list);
2957
2958
2959
2960
2961/* internal use functions */
2962
2963
2964uint32_t * mailimap_number_alloc_new(uint32_t number);
2965
2966void mailimap_number_alloc_free(uint32_t * pnumber);
2967
2968
2969void mailimap_addr_host_free(char * addr_host);
2970
2971void mailimap_addr_mailbox_free(char * addr_mailbox);
2972
2973void mailimap_addr_adl_free(char * addr_adl);
2974
2975void mailimap_addr_name_free(char * addr_name);
2976
2977void mailimap_astring_free(char * astring);
2978
2979void mailimap_atom_free(char * atom);
2980
2981void mailimap_auth_type_free(char * auth_type);
2982
2983void mailimap_base64_free(char * base64);
2984
2985void mailimap_body_fld_desc_free(char * body_fld_desc);
2986
2987void mailimap_body_fld_id_free(char * body_fld_id);
2988
2989void mailimap_body_fld_md5_free(char * body_fld_md5);
2990
2991void mailimap_env_date_free(char * date);
2992
2993void mailimap_env_in_reply_to_free(char * in_reply_to);
2994
2995void mailimap_env_message_id_free(char * message_id);
2996
2997void mailimap_env_subject_free(char * subject);
2998
2999void mailimap_flag_extension_free(char * flag_extension);
3000
3001void mailimap_flag_keyword_free(char * flag_keyword);
3002
3003void
3004mailimap_header_fld_name_free(char * header_fld_name);
3005
3006void mailimap_literal_free(char * literal);
3007
3008void mailimap_mailbox_free(char * mailbox);
3009
3010void
3011mailimap_mailbox_data_search_free(clist * data_search);
3012
3013void mailimap_media_subtype_free(char * media_subtype);
3014
3015void mailimap_media_text_free(char * media_text);
3016
3017void mailimap_msg_att_envelope_free(struct mailimap_envelope * env);
3018
3019void
3020mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time);
3021
3022void
3023mailimap_msg_att_rfc822_free(char * str);
3024
3025void
3026mailimap_msg_att_rfc822_header_free(char * str);
3027
3028void
3029mailimap_msg_att_rfc822_text_free(char * str);
3030
3031void
3032mailimap_msg_att_body_free(struct mailimap_body * body);
3033
3034void
3035mailimap_msg_att_bodystructure_free(struct mailimap_body * body);
3036
3037void mailimap_nstring_free(char * str);
3038
3039void
3040mailimap_string_free(char * str);
3041
3042void mailimap_tag_free(char * tag);
3043
3044void mailimap_text_free(char * text);
3045
3046
3047
3048
3049
3050/* IMAP connection */
3051
3052/* this is the state of the IMAP connection */
3053
3054enum {
3055 MAILIMAP_STATE_DISCONNECTED,
3056 MAILIMAP_STATE_NON_AUTHENTICATED,
3057 MAILIMAP_STATE_AUTHENTICATED,
3058 MAILIMAP_STATE_SELECTED,
3059 MAILIMAP_STATE_LOGOUT
3060};
3061
3062/*
3063 mailimap is an IMAP connection
3064
3065 - response is a human readable message returned with a reponse,
3066 must be accessed read-only
3067
3068 - stream is the connection with the IMAP server
3069
3070 - stream_buffer is the buffer where the data to parse are stored
3071
3072 - state is the state of IMAP connection
3073
3074 - tag is the current tag being used in IMAP connection
3075
3076 - response_buffer is the buffer for response messages
3077
3078 - connection_info is the information returned in response
3079 for the last command about the connection
3080
3081 - selection_info is the information returned in response
3082 for the last command about the current selected mailbox
3083
3084 - response_info is the other information returned in response
3085 for the last command
3086*/
3087
3088struct mailimap {
3089 char * imap_response;
3090
3091 /* internals */
3092 mailstream * imap_stream;
3093
3094 size_t imap_progr_rate;
3095 progress_function * imap_progr_fun;
3096
3097 MMAPString * imap_stream_buffer;
3098 MMAPString * imap_response_buffer;
3099
3100 int imap_state;
3101 int imap_tag;
3102
3103 struct mailimap_connection_info * imap_connection_info;
3104 struct mailimap_selection_info * imap_selection_info;
3105 struct mailimap_response_info * imap_response_info;
3106};
3107
3108typedef struct mailimap mailimap;
3109
3110
3111/*
3112 mailimap_connection_info is the information about the connection
3113
3114 - capability is the list of capability of the IMAP server
3115*/
3116
3117struct mailimap_connection_info {
3118 struct mailimap_capability_data * imap_capability;
3119};
3120
3121struct mailimap_connection_info *
3122mailimap_connection_info_new(void);
3123
3124void
3125mailimap_connection_info_free(struct mailimap_connection_info * conn_info);
3126
3127
3128/* this is the type of mailbox access */
3129
3130enum {
3131 MAILIMAP_MAILBOX_READONLY,
3132 MAILIMAP_MAILBOX_READWRITE
3133};
3134
3135/*
3136 mailimap_selection_info is information about the current selected mailbox
3137
3138 - perm_flags is a list of flags that can be changed permanently on the
3139 messages of the mailbox
3140
3141 - perm is the access on the mailbox, value can be
3142 MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE
3143
3144 - uidnext is the next unique identifier
3145
3146 - uidvalidity is the unique identifiers validity
3147
3148 - first_unseen is the number of the first unseen message
3149
3150 - flags is a list of flags that can be used on the messages of
3151 the mailbox
3152
3153 - exists is the number of messages in the mailbox
3154
3155 - recent is the number of recent messages in the mailbox
3156
3157 - unseen is the number of unseen messages in the mailbox
3158*/
3159
3160struct mailimap_selection_info {
3161 clist * sel_perm_flags; /* list of (struct flag_perm *) */
3162 int sel_perm;
3163 uint32_t sel_uidnext;
3164 uint32_t sel_uidvalidity;
3165 uint32_t sel_first_unseen;
3166 struct mailimap_flag_list * sel_flags;
3167 uint32_t sel_exists;
3168 uint32_t sel_recent;
3169 uint32_t sel_unseen;
3170};
3171
3172struct mailimap_selection_info *
3173mailimap_selection_info_new(void);
3174
3175void
3176mailimap_selection_info_free(struct mailimap_selection_info * sel_info);
3177
3178
3179/*
3180 mailimap_response_info is the other information returned in the
3181 response for a command
3182
3183 - alert is the human readable text returned with ALERT response
3184
3185 - parse is the human readable text returned with PARSE response
3186
3187 - badcharset is a list of charset returned with a BADCHARSET response
3188
3189 - trycreate is set to 1 if a trycreate response was returned
3190
3191 - mailbox_list is a list of mailboxes
3192
3193 - mailbox_lsub is a list of subscribed mailboxes
3194
3195 - search_result is a list of message numbers or unique identifiers
3196
3197 - status is a STATUS response
3198
3199 - expunged is a list of message numbers
3200
3201 - fetch_list is a list of fetch response
3202*/
3203
3204struct mailimap_response_info {
3205 char * rsp_alert;
3206 char * rsp_parse;
3207 clist * rsp_badcharset; /* list of (char *) */
3208 int rsp_trycreate;
3209 clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */
3210 clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */
3211 clist * rsp_search_result; /* list of (uint32_t *) */
3212 struct mailimap_mailbox_data_status * rsp_status;
3213 clist * rsp_expunged; /* list of (uint32_t 32 *) */
3214 clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */
3215};
3216
3217struct mailimap_response_info *
3218mailimap_response_info_new(void);
3219
3220void
3221mailimap_response_info_free(struct mailimap_response_info * resp_info);
3222
3223
3224/* these are the possible returned error codes */
3225
3226enum {
3227 MAILIMAP_NO_ERROR = 0,
3228 MAILIMAP_NO_ERROR_AUTHENTICATED = 1,
3229 MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2,
3230 MAILIMAP_ERROR_BAD_STATE,
3231 MAILIMAP_ERROR_STREAM,
3232 MAILIMAP_ERROR_PARSE,
3233 MAILIMAP_ERROR_CONNECTION_REFUSED,
3234 MAILIMAP_ERROR_MEMORY,
3235 MAILIMAP_ERROR_FATAL,
3236 MAILIMAP_ERROR_PROTOCOL,
3237 MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION,
3238 MAILIMAP_ERROR_APPEND,
3239 MAILIMAP_ERROR_NOOP,
3240 MAILIMAP_ERROR_LOGOUT,
3241 MAILIMAP_ERROR_CAPABILITY,
3242 MAILIMAP_ERROR_CHECK,
3243 MAILIMAP_ERROR_CLOSE,
3244 MAILIMAP_ERROR_EXPUNGE,
3245 MAILIMAP_ERROR_COPY,
3246 MAILIMAP_ERROR_UID_COPY,
3247 MAILIMAP_ERROR_CREATE,
3248 MAILIMAP_ERROR_DELETE,
3249 MAILIMAP_ERROR_EXAMINE,
3250 MAILIMAP_ERROR_FETCH,
3251 MAILIMAP_ERROR_UID_FETCH,
3252 MAILIMAP_ERROR_LIST,
3253 MAILIMAP_ERROR_LOGIN,
3254 MAILIMAP_ERROR_LSUB,
3255 MAILIMAP_ERROR_RENAME,
3256 MAILIMAP_ERROR_SEARCH,
3257 MAILIMAP_ERROR_UID_SEARCH,
3258 MAILIMAP_ERROR_SELECT,
3259 MAILIMAP_ERROR_STATUS,
3260 MAILIMAP_ERROR_STORE,
3261 MAILIMAP_ERROR_UID_STORE,
3262 MAILIMAP_ERROR_SUBSCRIBE,
3263 MAILIMAP_ERROR_UNSUBSCRIBE,
3264 MAILIMAP_ERROR_STARTTLS,
3265 MAILIMAP_ERROR_INVAL,
3266};
3267
3268
3269#ifdef __cplusplus
3270}
3271#endif
3272
3273#endif
3274
diff --git a/libetpan/src/low-level/imap/mailimap_types_helper.c b/libetpan/src/low-level/imap/mailimap_types_helper.c
new file mode 100644
index 0000000..574897b
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_types_helper.c
@@ -0,0 +1,1269 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimap_types.h"
37#include "mail.h"
38
39#include <stdlib.h>
40
41/* ************************************************************************* */
42/* ************************************************************************* */
43/* ************************************************************************* */
44/* ************************************************************************* */
45/* ************************************************************************* */
46/* ************************************************************************* */
47
48/* in helper */
49
50
51
52
53struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index)
54{
55 return mailimap_set_item_new(index, index);
56}
57
58struct mailimap_set *
59mailimap_set_new_single_item(struct mailimap_set_item * item)
60{
61 struct mailimap_set * set;
62 clist * list;
63 int r;
64
65 list = clist_new();
66 if (list == NULL)
67 return NULL;
68
69 r = clist_append(list, item);
70 if (r < 0) {
71 clist_free(list);
72 return NULL;
73 }
74
75 set = mailimap_set_new(list);
76 if (set == NULL) {
77 clist_free(list);
78 return NULL;
79 }
80
81 return set;
82}
83
84struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last)
85{
86 struct mailimap_set_item * item;
87 struct mailimap_set * set;
88
89 item = mailimap_set_item_new(first, last);
90 if (item == NULL)
91 return NULL;
92
93 set = mailimap_set_new_single_item(item);
94 if (set == NULL) {
95 mailimap_set_item_free(item);
96 return NULL;
97 }
98
99 return set;
100}
101
102struct mailimap_set * mailimap_set_new_single(uint32_t index)
103{
104 return mailimap_set_new_interval(index, index);
105}
106
107
108struct mailimap_set * mailimap_set_new_empty(void)
109{
110 clist * list;
111
112 list = clist_new();
113 if (list == NULL)
114 return NULL;
115
116 return mailimap_set_new(list);
117}
118
119int mailimap_set_add(struct mailimap_set * set,
120 struct mailimap_set_item * set_item)
121{
122 int r;
123
124 r = clist_append(set->set_list, set_item);
125 if (r < 0)
126 return MAILIMAP_ERROR_MEMORY;
127
128 return MAILIMAP_NO_ERROR;
129}
130
131int mailimap_set_add_interval(struct mailimap_set * set,
132 uint32_t first, uint32_t last)
133{
134 struct mailimap_set_item * item;
135 int r;
136
137 item = mailimap_set_item_new(first, last);
138 if (item == NULL)
139 return MAILIMAP_ERROR_MEMORY;
140
141 r = mailimap_set_add(set, item);
142 if (r != MAILIMAP_NO_ERROR) {
143 mailimap_set_item_free(item);
144 return r;
145 }
146 else
147 return MAILIMAP_NO_ERROR;
148}
149
150int mailimap_set_add_single(struct mailimap_set * set,
151 uint32_t index)
152{
153 return mailimap_set_add_interval(set, index, index);
154}
155
156/* CHECK */
157/* no args */
158
159/* CLOSE */
160/* no args */
161
162/* EXPUNGE */
163/* no args */
164
165/* COPY */
166/* set and gchar */
167
168/* FETCH */
169/* set and gchar fetch_type */
170
171
172
173/* section */
174
175#if 0
176/* not correct XXX */
177
178struct mailimap_section * mailimap_section_new_empty(void)
179{
180 clist * list;
181
182 list = clist_new();
183 if (list == NULL)
184 return NULL;
185
186 return mailimap_section_new(list);
187}
188#endif
189
190static struct mailimap_section *
191mailimap_section_new_msgtext(struct mailimap_section_msgtext * msgtext)
192{
193 struct mailimap_section_spec * spec;
194 struct mailimap_section * section;
195
196 spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT,
197 msgtext, NULL, NULL);
198 if (spec == NULL)
199 return NULL;
200
201 section = mailimap_section_new(spec);
202 if (section == NULL) {
203 /* detach section_msgtext so that it will not be freed */
204 spec->sec_data.sec_msgtext = NULL;
205 mailimap_section_spec_free(spec);
206 return NULL;
207 }
208
209 return section;
210}
211
212static struct mailimap_section *
213mailimap_section_new_part_msgtext(struct mailimap_section_part * part,
214 struct mailimap_section_msgtext * msgtext)
215{
216 struct mailimap_section_spec * spec;
217 struct mailimap_section * section;
218 struct mailimap_section_text * text;
219
220 text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT,
221 msgtext);
222 if (text == NULL)
223 return NULL;
224
225 spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART,
226 NULL, part, text);
227 if (spec == NULL) {
228 /* detach section_msgtext so that it will not be freed */
229 text->sec_msgtext = NULL;
230 mailimap_section_text_free(text);
231 return NULL;
232 }
233
234 section = mailimap_section_new(spec);
235 if (section == NULL) {
236 /* detach section_msgtext so that it will not be freed */
237 text->sec_msgtext = NULL;
238 mailimap_section_spec_free(spec);
239 return NULL;
240 }
241
242 return section;
243}
244
245/*
246HEADER
247HEADER.FIELDS fields
248HEADER.FIELDS.NOT fields
249TEXT
250*/
251
252struct mailimap_section * mailimap_section_new_header(void)
253{
254 struct mailimap_section_msgtext * msgtext;
255 struct mailimap_section * section;
256
257 msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER,
258 NULL);
259 if (msgtext == NULL)
260 return NULL;
261
262 section = mailimap_section_new_msgtext(msgtext);
263 if (section == NULL) {
264 mailimap_section_msgtext_free(msgtext);
265 return NULL;
266 }
267
268 return section;
269}
270
271struct mailimap_section *
272mailimap_section_new_header_fields(struct mailimap_header_list * header_list)
273{
274 struct mailimap_section * section;
275 struct mailimap_section_msgtext * msgtext;
276
277 msgtext =
278 mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS,
279 header_list);
280 if (msgtext == NULL)
281 return NULL;
282
283 section = mailimap_section_new_msgtext(msgtext);
284 if (section == NULL) {
285 /* detach header_list so that it will not be freed */
286 msgtext->sec_header_list = NULL;
287 mailimap_section_msgtext_free(msgtext);
288 return NULL;
289 }
290
291 return section;
292}
293
294struct mailimap_section *
295mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list)
296{
297 struct mailimap_section * section;
298 struct mailimap_section_msgtext * msgtext;
299
300 msgtext =
301 mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT,
302 header_list);
303 if (msgtext == NULL)
304 return NULL;
305
306 section = mailimap_section_new_msgtext(msgtext);
307 if (section == NULL) {
308 /* detach header_list so that it will not be freed */
309 msgtext->sec_header_list = NULL;
310 mailimap_section_msgtext_free(msgtext);
311 return NULL;
312 }
313
314 return section;
315}
316
317struct mailimap_section * mailimap_section_new_text(void)
318{
319 struct mailimap_section * section;
320 struct mailimap_section_msgtext * msgtext;
321
322 msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL);
323 if (msgtext == NULL)
324 return NULL;
325
326 section = mailimap_section_new_msgtext(msgtext);
327 if (section == NULL) {
328 mailimap_section_msgtext_free(msgtext);
329 return NULL;
330 }
331
332 return section;
333}
334
335/*
336section-part
337section-part . MIME
338section-part . HEADER
339section-part . HEADER.FIELDS fields
340section-part . HEADER.FIELDS.NOT fields
341section-part . TEXT
342*/
343
344struct mailimap_section *
345mailimap_section_new_part(struct mailimap_section_part * part)
346{
347 struct mailimap_section_spec * spec;
348 struct mailimap_section * section;
349
350 spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART,
351 NULL, part, NULL);
352 if (spec == NULL)
353 return NULL;
354
355 section = mailimap_section_new(spec);
356 if (section == NULL) {
357 /* detach section_part so that it will not be freed */
358 spec->sec_data.sec_part = NULL;
359 mailimap_section_spec_free(spec);
360 return NULL;
361 }
362
363 return section;
364}
365
366struct mailimap_section *
367mailimap_section_new_part_mime(struct mailimap_section_part * part)
368{
369 struct mailimap_section_spec * spec;
370 struct mailimap_section * section;
371 struct mailimap_section_text * text;
372
373 text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_MIME, NULL);
374 if (text == NULL)
375 return NULL;
376
377 spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART,
378 NULL, part, text);
379 if (spec == NULL) {
380 mailimap_section_text_free(text);
381 return NULL;
382 }
383
384 section = mailimap_section_new(spec);
385 if (section == NULL) {
386 /* detach section_part so that it will not be freed */
387 spec->sec_data.sec_part = NULL;
388 mailimap_section_spec_free(spec);
389 return NULL;
390 }
391
392 return section;
393}
394
395struct mailimap_section *
396mailimap_section_new_part_header(struct mailimap_section_part * part)
397{
398 struct mailimap_section_msgtext * msgtext;
399 struct mailimap_section * section;
400
401 msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER,
402 NULL);
403 if (msgtext == NULL)
404 return NULL;
405
406 section = mailimap_section_new_part_msgtext(part, msgtext);
407 if (section == NULL) {
408 mailimap_section_msgtext_free(msgtext);
409 return NULL;
410 }
411
412 return section;
413}
414
415struct mailimap_section *
416mailimap_section_new_part_header_fields(struct mailimap_section_part *
417 part,
418 struct mailimap_header_list *
419 header_list)
420{
421 struct mailimap_section * section;
422 struct mailimap_section_msgtext * msgtext;
423
424 msgtext =
425 mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS,
426 header_list);
427 if (msgtext == NULL)
428 return NULL;
429
430 section = mailimap_section_new_part_msgtext(part, msgtext);
431 if (section == NULL) {
432 /* detach header_list so that it will not be freed */
433 msgtext->sec_header_list = NULL;
434 mailimap_section_msgtext_free(msgtext);
435 return NULL;
436 }
437
438 return section;
439}
440
441struct mailimap_section *
442mailimap_section_new_part_header_fields_not(struct mailimap_section_part
443 * part,
444 struct mailimap_header_list
445 * header_list)
446{
447 struct mailimap_section * section;
448 struct mailimap_section_msgtext * msgtext;
449
450 msgtext =
451 mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT,
452 header_list);
453 if (msgtext == NULL)
454 return NULL;
455
456 section = mailimap_section_new_part_msgtext(part, msgtext);
457 if (section == NULL) {
458 /* detach header_list so that it will not be freed */
459 msgtext->sec_header_list = NULL;
460 mailimap_section_msgtext_free(msgtext);
461 return NULL;
462 }
463
464 return section;
465}
466
467struct mailimap_section *
468mailimap_section_new_part_text(struct mailimap_section_part * part)
469{
470 struct mailimap_section * section;
471 struct mailimap_section_msgtext * msgtext;
472
473 msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL);
474 if (msgtext == NULL)
475 return NULL;
476
477 section = mailimap_section_new_part_msgtext(part, msgtext);
478 if (section == NULL) {
479 mailimap_section_msgtext_free(msgtext);
480 return NULL;
481 }
482
483 return section;
484}
485
486/* end of section */
487
488
489
490
491
492
493struct mailimap_fetch_att *
494mailimap_fetch_att_new_envelope(void)
495{
496 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_ENVELOPE, NULL, 0, 0);
497}
498
499struct mailimap_fetch_att *
500mailimap_fetch_att_new_flags(void)
501{
502 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_FLAGS, NULL, 0, 0);
503}
504
505struct mailimap_fetch_att *
506mailimap_fetch_att_new_internaldate(void)
507{
508 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_INTERNALDATE, NULL, 0, 0);
509}
510
511struct mailimap_fetch_att *
512mailimap_fetch_att_new_rfc822(void)
513{
514 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822, NULL, 0, 0);
515}
516
517struct mailimap_fetch_att *
518mailimap_fetch_att_new_rfc822_header(void)
519{
520 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_HEADER, NULL, 0, 0);
521}
522
523struct mailimap_fetch_att *
524mailimap_fetch_att_new_rfc822_size(void)
525{
526 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_SIZE, NULL, 0, 0);
527}
528
529struct mailimap_fetch_att *
530mailimap_fetch_att_new_rfc822_text(void)
531{
532 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_TEXT, NULL, 0, 0);
533}
534
535struct mailimap_fetch_att *
536mailimap_fetch_att_new_body(void)
537{
538 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY, NULL, 0, 0);
539}
540
541struct mailimap_fetch_att *
542mailimap_fetch_att_new_bodystructure(void)
543{
544 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODYSTRUCTURE, NULL, 0, 0);
545}
546
547struct mailimap_fetch_att *
548mailimap_fetch_att_new_uid(void)
549{
550 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_UID, NULL, 0, 0);
551}
552
553struct mailimap_fetch_att *
554mailimap_fetch_att_new_body_section(struct mailimap_section * section)
555{
556 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, 0, 0);
557}
558
559struct mailimap_fetch_att *
560mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section)
561{
562 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, 0, 0);
563}
564
565struct mailimap_fetch_att *
566mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section,
567 uint32_t offset, uint32_t size)
568{
569 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section,
570 offset, size);
571}
572
573struct mailimap_fetch_att *
574mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section,
575 uint32_t offset, uint32_t size)
576{
577 return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section,
578 offset, size);
579}
580
581
582
583struct mailimap_fetch_type *
584mailimap_fetch_type_new_all(void)
585{
586 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_ALL, NULL, NULL);
587}
588
589struct mailimap_fetch_type *
590mailimap_fetch_type_new_full(void)
591{
592 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FULL, NULL, NULL);
593}
594
595struct mailimap_fetch_type *
596mailimap_fetch_type_new_fast(void)
597{
598 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FAST, NULL, NULL);
599}
600
601struct mailimap_fetch_type *
602mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att)
603{
604 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT, fetch_att, NULL);
605}
606
607struct mailimap_fetch_type *
608mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list)
609{
610 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST,
611 NULL, fetch_att_list);
612}
613
614struct mailimap_fetch_type *
615mailimap_fetch_type_new_fetch_att_list_empty(void)
616{
617 clist * list;
618
619 list = clist_new();
620 if (list == NULL)
621 return NULL;
622
623 return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST,
624 NULL, list);
625}
626
627int
628mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type *
629 fetch_type,
630 struct mailimap_fetch_att * fetch_att)
631{
632 int r;
633
634 r = clist_append(fetch_type->ft_data.ft_fetch_att_list, fetch_att);
635 if (r < 0)
636 return MAILIMAP_ERROR_MEMORY;
637
638 return MAILIMAP_NO_ERROR;
639}
640
641
642
643/* STORE */
644/* set and store_att_flags */
645
646struct mailimap_store_att_flags *
647mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags)
648{
649 return mailimap_store_att_flags_new(0, FALSE, flags);
650}
651
652struct mailimap_store_att_flags *
653mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list *
654 flags)
655{
656 return mailimap_store_att_flags_new(0, TRUE, flags);
657}
658
659struct mailimap_store_att_flags *
660mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags)
661{
662 return mailimap_store_att_flags_new(1, FALSE, flags);
663}
664
665struct mailimap_store_att_flags *
666mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list *
667 flags)
668{
669 return mailimap_store_att_flags_new(1, TRUE, flags);
670}
671
672struct mailimap_store_att_flags *
673mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags)
674{
675 return mailimap_store_att_flags_new(-1, FALSE, flags);
676}
677
678struct mailimap_store_att_flags *
679mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list *
680 flags)
681{
682 return mailimap_store_att_flags_new(-1, TRUE, flags);
683}
684
685/* SEARCH */
686/* date search-key set */
687
688/*
689 return mailimap_search_key_new(type, bcc, before,
690 body, cc, from, keyword, on, since,
691 subject, text, to, unkeyword, header_name,
692 header_value, larger, not,
693 or1, or2, sentbefore, senton, sentsince,
694 smaller, uid, set, multiple);
695*/
696
697struct mailimap_search_key *
698mailimap_search_key_new_all(void)
699{
700 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ALL, NULL, NULL,
701 NULL, NULL, NULL, NULL, NULL, NULL,
702 NULL, NULL, NULL, NULL, NULL,
703 NULL, 0, NULL,
704 NULL, NULL, NULL, NULL, NULL,
705 0, NULL, NULL, NULL);
706}
707
708struct mailimap_search_key *
709mailimap_search_key_new_bcc(char * sk_bcc)
710{
711 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BCC, sk_bcc, NULL,
712 NULL, NULL, NULL, NULL, NULL, NULL,
713 NULL, NULL, NULL, NULL, NULL,
714 NULL, 0, NULL,
715 NULL, NULL, NULL, NULL, NULL,
716 0, NULL, NULL, NULL);
717}
718
719struct mailimap_search_key *
720mailimap_search_key_new_before(struct mailimap_date * sk_before)
721{
722 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BEFORE, NULL, sk_before,
723 NULL, NULL, NULL, NULL, NULL, NULL,
724 NULL, NULL, NULL, NULL, NULL,
725 NULL, 0, NULL,
726 NULL, NULL, NULL, NULL, NULL,
727 0, NULL, NULL, NULL);
728}
729
730struct mailimap_search_key *
731mailimap_search_key_new_body(char * sk_body)
732{
733 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BODY, NULL, NULL,
734 sk_body, NULL, NULL, NULL, NULL, NULL,
735 NULL, NULL, NULL, NULL, NULL,
736 NULL, 0, NULL,
737 NULL, NULL, NULL, NULL, NULL,
738 0, NULL, NULL, NULL);
739}
740
741struct mailimap_search_key *
742mailimap_search_key_new_cc(char * sk_cc)
743{
744 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_CC, NULL, NULL,
745 NULL, sk_cc, NULL, NULL, NULL, NULL,
746 NULL, NULL, NULL, NULL, NULL,
747 NULL, 0, NULL,
748 NULL, NULL, NULL, NULL, NULL,
749 0, NULL, NULL, NULL);
750}
751
752struct mailimap_search_key *
753mailimap_search_key_new_from(char * sk_from)
754{
755 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL,
756 NULL, NULL, sk_from, NULL, NULL, NULL,
757 NULL, NULL, NULL, NULL, NULL,
758 NULL, 0, NULL,
759 NULL, NULL, NULL, NULL, NULL,
760 0, NULL, NULL, NULL);
761}
762
763struct mailimap_search_key *
764mailimap_search_key_new_keyword(char * sk_keyword)
765{
766 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL,
767 NULL, NULL, NULL, sk_keyword, NULL, NULL,
768 NULL, NULL, NULL, NULL, NULL,
769 NULL, 0, NULL,
770 NULL, NULL, NULL, NULL, NULL,
771 0, NULL, NULL, NULL);
772}
773
774struct mailimap_search_key *
775mailimap_search_key_new_on(struct mailimap_date * sk_on)
776{
777 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ON, NULL, NULL,
778 NULL, NULL, NULL, NULL, sk_on, NULL,
779 NULL, NULL, NULL, NULL, NULL,
780 NULL, 0, NULL,
781 NULL, NULL, NULL, NULL, NULL,
782 0, NULL, NULL, NULL);
783}
784
785struct mailimap_search_key *
786mailimap_search_key_new_since(struct mailimap_date * sk_since)
787{
788 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL,
789 NULL, NULL, NULL, NULL, NULL, sk_since,
790 NULL, NULL, NULL, NULL, NULL,
791 NULL, 0, NULL,
792 NULL, NULL, NULL, NULL, NULL,
793 0, NULL, NULL, NULL);
794}
795
796struct mailimap_search_key *
797mailimap_search_key_new_subject(char * sk_subject)
798{
799 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL,
800 NULL, NULL, NULL, NULL, NULL, NULL,
801 sk_subject, NULL, NULL, NULL, NULL,
802 NULL, 0, NULL,
803 NULL, NULL, NULL, NULL, NULL,
804 0, NULL, NULL, NULL);
805}
806
807struct mailimap_search_key *
808mailimap_search_key_new_text(char * sk_text)
809{
810 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TEXT, NULL, NULL,
811 NULL, NULL, NULL, NULL, NULL, NULL,
812 NULL, sk_text, NULL, NULL, NULL,
813 NULL, 0, NULL,
814 NULL, NULL, NULL, NULL, NULL,
815 0, NULL, NULL, NULL);
816}
817
818struct mailimap_search_key *
819mailimap_search_key_new_to(char * sk_to)
820{
821 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TO, NULL, NULL,
822 NULL, NULL, NULL, NULL, NULL, NULL,
823 NULL, NULL, sk_to, NULL, NULL,
824 NULL, 0, NULL,
825 NULL, NULL, NULL, NULL, NULL,
826 0, NULL, NULL, NULL);
827}
828
829struct mailimap_search_key *
830mailimap_search_key_new_unkeyword(char * sk_unkeyword)
831{
832 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNKEYWORD, NULL, NULL,
833 NULL, NULL, NULL, NULL, NULL, NULL,
834 NULL, NULL, NULL, sk_unkeyword, NULL,
835 NULL, 0, NULL,
836 NULL, NULL, NULL, NULL, NULL,
837 0, NULL, NULL, NULL);
838}
839
840struct mailimap_search_key *
841mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value)
842{
843 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_HEADER, NULL, NULL,
844 NULL, NULL, NULL, NULL, NULL, NULL,
845 NULL, NULL, NULL, NULL, sk_header_name,
846 sk_header_value, 0, NULL,
847 NULL, NULL, NULL, NULL, NULL,
848 0, NULL, NULL, NULL);
849}
850
851struct mailimap_search_key *
852mailimap_search_key_new_larger(uint32_t sk_larger)
853{
854 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_LARGER, NULL, NULL,
855 NULL, NULL, NULL, NULL, NULL, NULL,
856 NULL, NULL, NULL, NULL, NULL,
857 NULL, sk_larger, NULL,
858 NULL, NULL, NULL, NULL, NULL,
859 0, NULL, NULL, NULL);
860}
861
862struct mailimap_search_key *
863mailimap_search_key_new_not(struct mailimap_search_key * sk_not)
864{
865 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL,
866 NULL, NULL, NULL, NULL, NULL, NULL,
867 NULL, NULL, NULL, NULL, NULL,
868 NULL, 0, sk_not,
869 NULL, NULL, NULL, NULL, NULL,
870 0, NULL, NULL, NULL);
871}
872
873struct mailimap_search_key *
874mailimap_search_key_new_or(struct mailimap_search_key * sk_or1,
875 struct mailimap_search_key * sk_or2)
876{
877 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_OR, NULL, NULL,
878 NULL, NULL, NULL, NULL, NULL, NULL,
879 NULL, NULL, NULL, NULL, NULL,
880 NULL, 0, NULL,
881 sk_or1, sk_or2, NULL, NULL, NULL,
882 0, NULL, NULL, NULL);
883}
884
885struct mailimap_search_key *
886mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore)
887{
888 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL,
889 NULL, NULL, NULL, NULL, NULL, NULL,
890 NULL, NULL, NULL, NULL, NULL,
891 NULL, 0, NULL,
892 NULL, NULL, sk_sentbefore, NULL, NULL,
893 0, NULL, NULL, NULL);
894}
895
896struct mailimap_search_key *
897mailimap_search_key_new_senton(struct mailimap_date * sk_senton)
898{
899 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTON, NULL, NULL,
900 NULL, NULL, NULL, NULL, NULL, NULL,
901 NULL, NULL, NULL, NULL, NULL,
902 NULL, 0, NULL,
903 NULL, NULL, NULL, sk_senton, NULL,
904 0, NULL, NULL, NULL);
905}
906
907struct mailimap_search_key *
908mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince)
909{
910 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTSINCE, NULL, NULL,
911 NULL, NULL, NULL, NULL, NULL, NULL,
912 NULL, NULL, NULL, NULL, NULL,
913 NULL, 0, NULL,
914 NULL, NULL, NULL, NULL, sk_sentsince,
915 0, NULL, NULL, NULL);
916}
917
918struct mailimap_search_key *
919mailimap_search_key_new_smaller(uint32_t sk_smaller)
920{
921 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SMALLER, NULL, NULL,
922 NULL, NULL, NULL, NULL, NULL, NULL,
923 NULL, NULL, NULL, NULL, NULL,
924 NULL, 0, NULL,
925 NULL, NULL, NULL, NULL, NULL,
926 sk_smaller, NULL, NULL, NULL);
927}
928
929struct mailimap_search_key *
930mailimap_search_key_new_uid(struct mailimap_set * sk_uid)
931{
932 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UID, NULL, NULL,
933 NULL, NULL, NULL, NULL, NULL, NULL,
934 NULL, NULL, NULL, NULL, NULL,
935 NULL, 0, NULL,
936 NULL, NULL, NULL, NULL, NULL,
937 0, sk_uid, NULL, NULL);
938}
939
940struct mailimap_search_key *
941mailimap_search_key_new_set(struct mailimap_set * sk_set)
942{
943 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SET, NULL, NULL,
944 NULL, NULL, NULL, NULL, NULL, NULL,
945 NULL, NULL, NULL, NULL, NULL,
946 NULL, 0, NULL,
947 NULL, NULL, NULL, NULL, NULL,
948 0, NULL, sk_set, NULL);
949}
950
951struct mailimap_search_key *
952mailimap_search_key_new_multiple(clist * sk_multiple)
953{
954 return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_MULTIPLE, NULL, NULL,
955 NULL, NULL, NULL, NULL, NULL, NULL,
956 NULL, NULL, NULL, NULL, NULL,
957 NULL, 0, NULL,
958 NULL, NULL, NULL, NULL, NULL,
959 0, NULL, NULL, sk_multiple);
960}
961
962struct mailimap_search_key *
963mailimap_search_key_new_multiple_empty(void)
964{
965 clist * list;
966
967 list = clist_new();
968 if (list == NULL)
969 return NULL;
970
971 return mailimap_search_key_new_multiple(list);
972}
973
974int
975mailimap_search_key_multiple_add(struct mailimap_search_key * keys,
976 struct mailimap_search_key * key_item)
977{
978 int r;
979
980 r = clist_append(keys->sk_data.sk_multiple, key_item);
981 if (r < 0)
982 return MAILIMAP_ERROR_MEMORY;
983
984 return MAILIMAP_NO_ERROR;
985}
986
987
988
989/* CAPABILITY */
990/* no args */
991
992/* LOGOUT */
993/* no args */
994
995/* NOOP */
996/* no args */
997
998/* APPEND */
999/* gchar flag_list date_time gchar */
1000
1001struct mailimap_flag_list *
1002mailimap_flag_list_new_empty(void)
1003{
1004 clist * list;
1005
1006 list = clist_new();
1007 if (list == NULL)
1008 return NULL;
1009
1010 return mailimap_flag_list_new(list);
1011}
1012
1013int mailimap_flag_list_add(struct mailimap_flag_list * flag_list,
1014 struct mailimap_flag * f)
1015{
1016 int r;
1017
1018 r = clist_append(flag_list->fl_list, f);
1019 if (r < 0)
1020 return MAILIMAP_ERROR_MEMORY;
1021
1022 return MAILIMAP_NO_ERROR;
1023}
1024
1025struct mailimap_flag * mailimap_flag_new_answered(void)
1026{
1027 return mailimap_flag_new(MAILIMAP_FLAG_ANSWERED, NULL, NULL);
1028}
1029
1030struct mailimap_flag * mailimap_flag_new_flagged(void)
1031{
1032 return mailimap_flag_new(MAILIMAP_FLAG_FLAGGED, NULL, NULL);
1033}
1034
1035struct mailimap_flag * mailimap_flag_new_deleted(void)
1036{
1037 return mailimap_flag_new(MAILIMAP_FLAG_DELETED, NULL, NULL);
1038}
1039
1040struct mailimap_flag * mailimap_flag_new_seen(void)
1041{
1042 return mailimap_flag_new(MAILIMAP_FLAG_SEEN, NULL, NULL);
1043}
1044
1045struct mailimap_flag * mailimap_flag_new_draft(void)
1046{
1047 return mailimap_flag_new(MAILIMAP_FLAG_DRAFT, NULL, NULL);
1048}
1049
1050struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword)
1051{
1052 return mailimap_flag_new(MAILIMAP_FLAG_KEYWORD, flag_keyword, NULL);
1053}
1054
1055struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension)
1056{
1057 return mailimap_flag_new(MAILIMAP_FLAG_EXTENSION, NULL, flag_extension);
1058}
1059
1060
1061
1062
1063/* CREATE */
1064/* gchar */
1065
1066/* DELETE */
1067/* gchar */
1068
1069/* EXAMINE */
1070/* gchar */
1071
1072/* LIST */
1073/* gchar gchar */
1074
1075/* LSUB */
1076/* gchar gchar */
1077
1078/* RENAME */
1079/* gchar gchar */
1080
1081/* SELECT */
1082/* gchar */
1083
1084/* STATUS */
1085/* gchar GList of status_att */
1086
1087struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void)
1088{
1089 clist * list;
1090
1091 list = clist_new();
1092 if (list == NULL)
1093 return NULL;
1094
1095 return mailimap_status_att_list_new(list);
1096}
1097
1098int
1099mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list,
1100 int status_att)
1101{
1102 int * pstatus_att;
1103 int r;
1104
1105 pstatus_att = malloc(sizeof(* pstatus_att));
1106 * pstatus_att = status_att;
1107
1108 r = clist_append(sa_list->att_list, pstatus_att);
1109 if (r < 0) {
1110 free(pstatus_att);
1111 return MAILIMAP_ERROR_MEMORY;
1112 }
1113
1114 return MAILIMAP_NO_ERROR;
1115}
1116
1117/* SUBSCRIBE */
1118/* gchar */
1119
1120/* UNSUBSCRIBE */
1121/* gchar */
1122
1123/* LOGIN */
1124/* gchar gchar */
1125
1126/* AUTHENTICATE */
1127/* gchar */
1128
1129
1130static int recursive_build_path(struct mailimap_body * root_part,
1131 struct mailimap_body * part,
1132 clist ** result);
1133
1134static int try_build_part(struct mailimap_body * root_part,
1135 struct mailimap_body * part, uint32_t count,
1136 clist ** result)
1137{
1138 int r;
1139 clist * imap_id_list;
1140 uint32_t * id;
1141
1142 r = recursive_build_path(root_part, part, &imap_id_list);
1143 if (r != MAILIMAP_NO_ERROR)
1144 return r;
1145
1146 id = malloc(sizeof(* id));
1147 if (id == NULL) {
1148 clist_free(imap_id_list);
1149 return MAILIMAP_ERROR_MEMORY;
1150 }
1151
1152 * id = count;
1153
1154 r = clist_prepend(imap_id_list, id);
1155 if (r < 0) {
1156 free(id);
1157 clist_free(imap_id_list);
1158 return MAILIMAP_ERROR_MEMORY;
1159 }
1160
1161 * result = imap_id_list;
1162
1163 return MAILIMAP_NO_ERROR;
1164}
1165
1166
1167static int recursive_build_path(struct mailimap_body * root_part,
1168 struct mailimap_body * part,
1169 clist ** result)
1170{
1171 clistiter * cur;
1172 uint32_t count;
1173 int r;
1174 clist * imap_id_list;
1175
1176 if (part == root_part) {
1177 imap_id_list = clist_new();
1178 if (imap_id_list == NULL) {
1179 return MAILIMAP_ERROR_MEMORY;
1180 }
1181
1182 * result = imap_id_list;
1183
1184 return MAILIMAP_NO_ERROR;
1185 }
1186
1187 switch (root_part->bd_type) {
1188 case MAILIMAP_BODY_MPART:
1189 count = 0;
1190 for(cur = clist_begin(root_part->bd_data.bd_body_mpart->bd_list) ;
1191 cur != NULL ; cur = clist_next(cur)) {
1192 struct mailimap_body * current_part;
1193
1194 current_part = clist_content(cur);
1195 count ++;
1196
1197 r = try_build_part(current_part, part, count, &imap_id_list);
1198 if (r == MAILIMAP_ERROR_INVAL) {
1199 continue;
1200 } if (r != MAILIMAP_NO_ERROR) {
1201 return r;
1202 }
1203 else {
1204 * result = imap_id_list;
1205 return MAILIMAP_NO_ERROR;
1206 }
1207 }
1208 return MAILIMAP_ERROR_INVAL;
1209
1210 case MAILIMAP_BODY_1PART:
1211 if (root_part->bd_data.bd_body_1part->bd_type ==
1212 MAILIMAP_BODY_TYPE_1PART_MSG) {
1213 struct mailimap_body * current_part;
1214
1215 current_part =
1216 root_part->bd_data.bd_body_1part->bd_data.bd_type_msg->bd_body;
1217
1218 r = try_build_part(current_part, part, 1, &imap_id_list);
1219 if (r != MAILIMAP_NO_ERROR) {
1220 return r;
1221 }
1222 else {
1223 * result = imap_id_list;
1224 return MAILIMAP_NO_ERROR;
1225 }
1226 }
1227 else {
1228 return MAILIMAP_ERROR_INVAL;
1229 }
1230 break;
1231
1232 default:
1233 return MAILIMAP_ERROR_INVAL;
1234 }
1235}
1236
1237/* return mailimap_section_part from a given mailimap_body */
1238
1239int mailimap_get_section_part_from_body(struct mailimap_body * root_part,
1240 struct mailimap_body * part,
1241 struct mailimap_section_part ** result)
1242{
1243 struct mailimap_section_part * section_part;
1244 clist * id_list;
1245 int r;
1246 int res;
1247
1248 r = recursive_build_path(root_part, part, &id_list);
1249 if (r != MAILIMAP_NO_ERROR) {
1250 res = r;
1251 goto err;
1252 }
1253
1254 section_part = mailimap_section_part_new(id_list);
1255 if (section_part == NULL) {
1256 res = MAILIMAP_ERROR_MEMORY;
1257 goto free_list;
1258 }
1259
1260 * result = section_part;
1261
1262 return MAILIMAP_NO_ERROR;
1263
1264 free_list:
1265 clist_foreach(id_list, (clist_func) free, NULL);
1266 clist_free(id_list);
1267 err:
1268 return res;
1269}
diff --git a/libetpan/src/low-level/imap/mailimap_types_helper.h b/libetpan/src/low-level/imap/mailimap_types_helper.h
new file mode 100644
index 0000000..10905d4
--- a/dev/null
+++ b/libetpan/src/low-level/imap/mailimap_types_helper.h
@@ -0,0 +1,758 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMAP_TYPES_HELPER_H
37
38#define MAILIMAP_TYPES_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimap_types.h>
45
46/*
47 IMPORTANT NOTE:
48
49 All allocation functions will take as argument allocated data
50 and will store these data in the structure they will allocate.
51 Data should be persistant during all the use of the structure
52 and will be freed by the free function of the structure
53
54 allocation functions will return NULL on failure
55*/
56
57/*
58 this function creates a new set item with a single message
59 given by index
60*/
61
62struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index);
63
64/*
65 this function creates a new set with one set item
66 */
67
68struct mailimap_set *
69mailimap_set_new_single_item(struct mailimap_set_item * item);
70
71/*
72 this function creates a set with a single interval
73*/
74
75struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last);
76
77/*
78 this function creates a set with a single message
79*/
80
81struct mailimap_set * mailimap_set_new_single(uint32_t index);
82
83/*
84 this function creates an empty set of messages
85*/
86
87struct mailimap_set * mailimap_set_new_empty(void);
88
89/*
90 this function adds a set item to the set of messages
91
92 @return MAILIMAP_NO_ERROR will be returned on success,
93 other code will be returned otherwise
94*/
95
96int mailimap_set_add(struct mailimap_set * set,
97 struct mailimap_set_item * set_item);
98
99/*
100 this function adds an interval to the set
101
102 @return MAILIMAP_NO_ERROR will be returned on success,
103 other code will be returned otherwise
104*/
105
106int mailimap_set_add_interval(struct mailimap_set * set,
107 uint32_t first, uint32_t last);
108
109/*
110 this function adds a single message to the set
111
112 @return MAILIMAP_NO_ERROR will be returned on success,
113 other code will be returned otherwise
114*/
115
116int mailimap_set_add_single(struct mailimap_set * set,
117 uint32_t index);
118
119/*
120 this function creates a mailimap_section structure to request
121 the header of a message
122*/
123
124struct mailimap_section * mailimap_section_new_header(void);
125
126/*
127 this functions creates a mailimap_section structure to describe
128 a list of headers
129*/
130
131struct mailimap_section *
132mailimap_section_new_header_fields(struct mailimap_header_list * header_list);
133
134/*
135 this functions creates a mailimap_section structure to describe headers
136 other than those given
137*/
138
139struct mailimap_section *
140mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list);
141
142/*
143 this function creates a mailimap_section structure to describe the
144 text of a message
145 */
146
147struct mailimap_section * mailimap_section_new_text(void);
148
149/*
150 this function creates a mailimap_section structure to describe the
151 content of a MIME part
152*/
153
154struct mailimap_section *
155mailimap_section_new_part(struct mailimap_section_part * part);
156
157/*
158 this function creates a mailimap_section structure to describe the
159 MIME fields of a MIME part
160*/
161
162struct mailimap_section *
163mailimap_section_new_part_mime(struct mailimap_section_part * part);
164
165/*
166 this function creates a mailimap_section structure to describe the
167 headers of a MIME part if the MIME type is a message/rfc822
168*/
169
170struct mailimap_section *
171mailimap_section_new_part_header(struct mailimap_section_part * part);
172
173/*
174 this function creates a mailimap_section structure to describe
175 a list of headers of a MIME part if the MIME type is a message/rfc822
176*/
177
178struct mailimap_section *
179mailimap_section_new_part_header_fields(struct mailimap_section_part *
180 part,
181 struct mailimap_header_list *
182 header_list);
183
184/*
185 this function creates a mailimap_section structure to describe
186 headers of a MIME part other than those given if the MIME type
187 is a message/rfc822
188*/
189
190struct mailimap_section *
191mailimap_section_new_part_header_fields_not(struct mailimap_section_part
192 * part,
193 struct mailimap_header_list
194 * header_list);
195
196/*
197 this function creates a mailimap_section structure to describe
198 text part of message if the MIME type is a message/rfc822
199*/
200
201struct mailimap_section *
202mailimap_section_new_part_text(struct mailimap_section_part * part);
203
204
205/*
206 this function creates a mailimap_fetch_att structure to request
207 envelope of a message
208*/
209
210struct mailimap_fetch_att *
211mailimap_fetch_att_new_envelope(void);
212
213
214/*
215 this function creates a mailimap_fetch_att structure to request
216 flags of a message
217*/
218
219struct mailimap_fetch_att *
220mailimap_fetch_att_new_flags(void);
221
222/*
223 this function creates a mailimap_fetch_att structure to request
224 internal date of a message
225*/
226
227struct mailimap_fetch_att *
228mailimap_fetch_att_new_internaldate(void);
229
230
231/*
232 this function creates a mailimap_fetch_att structure to request
233 text part of a message
234*/
235
236struct mailimap_fetch_att *
237mailimap_fetch_att_new_rfc822(void);
238
239
240/*
241 this function creates a mailimap_fetch_att structure to request
242 header of a message
243*/
244
245struct mailimap_fetch_att *
246mailimap_fetch_att_new_rfc822_header(void);
247
248/*
249 this function creates a mailimap_fetch_att structure to request
250 size of a message
251*/
252
253struct mailimap_fetch_att *
254mailimap_fetch_att_new_rfc822_size(void);
255
256/*
257 this function creates a mailimap_fetch_att structure to request
258 envelope of a message
259*/
260
261struct mailimap_fetch_att *
262mailimap_fetch_att_new_rfc822_text(void);
263
264/*
265 this function creates a mailimap_fetch_att structure to request
266 the MIME structure of a message
267*/
268
269struct mailimap_fetch_att *
270mailimap_fetch_att_new_body(void);
271
272/*
273 this function creates a mailimap_fetch_att structure to request
274 the MIME structure of a message and additional MIME information
275*/
276
277struct mailimap_fetch_att *
278mailimap_fetch_att_new_bodystructure(void);
279
280/*
281 this function creates a mailimap_fetch_att structure to request
282 unique identifier of a message
283*/
284
285struct mailimap_fetch_att *
286mailimap_fetch_att_new_uid(void);
287
288/*
289 this function creates a mailimap_fetch_att structure to request
290 a given section of a message
291*/
292
293struct mailimap_fetch_att *
294mailimap_fetch_att_new_body_section(struct mailimap_section * section);
295
296/*
297 this function creates a mailimap_fetch_att structure to request
298 a given section of a message without marking it as read
299*/
300
301struct mailimap_fetch_att *
302mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section);
303
304/*
305 this function creates a mailimap_fetch_att structure to request
306 a part of a section of a message
307*/
308
309struct mailimap_fetch_att *
310mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section,
311 uint32_t offset, uint32_t size);
312
313/*
314 this function creates a mailimap_fetch_att structure to request
315 a part of a section of a message without marking it as read
316*/
317
318struct mailimap_fetch_att *
319mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section,
320 uint32_t offset, uint32_t size);
321
322/*
323 this function creates a mailimap_fetch_type structure to request
324 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message
325*/
326
327struct mailimap_fetch_type *
328mailimap_fetch_type_new_all(void);
329
330/*
331 this function creates a mailimap_fetch_type structure to request
332 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY)
333*/
334
335struct mailimap_fetch_type *
336mailimap_fetch_type_new_full(void);
337
338/*
339 this function creates a mailimap_fetch_type structure to request
340 (FLAGS INTERNALDATE RFC822.SIZE)
341*/
342
343struct mailimap_fetch_type *
344mailimap_fetch_type_new_fast(void);
345
346/*
347 this function creates a mailimap_fetch_type structure to request
348 the given fetch attribute
349*/
350
351struct mailimap_fetch_type *
352mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att);
353
354/*
355 this function creates a mailimap_fetch_type structure to request
356 the list of fetch attributes
357*/
358
359struct mailimap_fetch_type *
360mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list);
361
362/*
363 this function creates a mailimap_fetch_type structure
364*/
365
366struct mailimap_fetch_type *
367mailimap_fetch_type_new_fetch_att_list_empty(void);
368
369/*
370 this function adds a given fetch attribute to the mailimap_fetch
371 structure
372
373 @return MAILIMAP_NO_ERROR will be returned on success,
374 other code will be returned otherwise
375*/
376
377int
378mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type *
379 fetch_type,
380 struct mailimap_fetch_att *
381 fetch_att);
382
383/*
384 this function creates a store attribute to set the given flags
385*/
386
387struct mailimap_store_att_flags *
388mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags);
389
390/*
391 this function creates a store attribute to silently set the given flags
392*/
393
394struct mailimap_store_att_flags *
395mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list *
396 flags);
397
398/*
399 this function creates a store attribute to add the given flags
400*/
401
402struct mailimap_store_att_flags *
403mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags);
404
405/*
406 this function creates a store attribute to add silently the given flags
407*/
408
409struct mailimap_store_att_flags *
410mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list *
411 flags);
412
413/*
414 this function creates a store attribute to remove the given flags
415*/
416
417struct mailimap_store_att_flags *
418mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags);
419
420/*
421 this function creates a store attribute to remove silently the given flags
422*/
423
424struct mailimap_store_att_flags *
425mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list *
426 flags);
427
428
429/*
430 this function creates a condition structure to match all messages
431*/
432
433struct mailimap_search_key *
434mailimap_search_key_new_all(void);
435
436/*
437 this function creates a condition structure to match messages with Bcc field
438
439 @param bcc this is the content of Bcc to match, it should be allocated
440 with malloc()
441*/
442
443struct mailimap_search_key *
444mailimap_search_key_new_bcc(char * sk_bcc);
445
446/*
447 this function creates a condition structure to match messages with
448 internal date
449*/
450
451struct mailimap_search_key *
452mailimap_search_key_new_before(struct mailimap_date * sk_before);
453
454/*
455 this function creates a condition structure to match messages with
456 message content
457
458 @param body this is the content of the message to match, it should
459 be allocated with malloc()
460*/
461
462struct mailimap_search_key *
463mailimap_search_key_new_body(char * sk_body);
464
465/*
466 this function creates a condition structure to match messages with
467 Cc field
468
469
470 @param cc this is the content of Cc to match, it should be allocated
471 with malloc()
472*/
473
474struct mailimap_search_key *
475mailimap_search_key_new_cc(char * sk_cc);
476
477/*
478 this function creates a condition structure to match messages with
479 From field
480
481 @param from this is the content of From to match, it should be allocated
482 with malloc()
483*/
484
485struct mailimap_search_key *
486mailimap_search_key_new_from(char * sk_from);
487
488/*
489 this function creates a condition structure to match messages with
490 a flag given by keyword
491*/
492
493struct mailimap_search_key *
494mailimap_search_key_new_keyword(char * sk_keyword);
495
496/*
497 this function creates a condition structure to match messages with
498 internal date
499*/
500
501struct mailimap_search_key *
502mailimap_search_key_new_on(struct mailimap_date * sk_on);
503
504/*
505 this function creates a condition structure to match messages with
506 internal date
507*/
508
509struct mailimap_search_key *
510mailimap_search_key_new_since(struct mailimap_date * sk_since);
511
512/*
513 this function creates a condition structure to match messages with
514 Subject field
515
516 @param subject this is the content of Subject to match, it should
517 be allocated with malloc()
518*/
519
520struct mailimap_search_key *
521mailimap_search_key_new_subject(char * sk_subject);
522
523/*
524 this function creates a condition structure to match messages with
525 message text part
526
527 @param text this is the message text to match, it should
528 be allocated with malloc()
529*/
530
531struct mailimap_search_key *
532mailimap_search_key_new_text(char * sk_text);
533
534/*
535 this function creates a condition structure to match messages with
536 To field
537
538 @param to this is the content of To to match, it should be allocated
539 with malloc()
540*/
541
542struct mailimap_search_key *
543mailimap_search_key_new_to(char * sk_to);
544
545/*
546 this function creates a condition structure to match messages with
547 no a flag given by unkeyword
548*/
549
550struct mailimap_search_key *
551mailimap_search_key_new_unkeyword(char * sk_unkeyword);
552
553/*
554 this function creates a condition structure to match messages with
555 the given field
556
557 @param header_name this is the name of the field to match, it
558 should be allocated with malloc()
559
560 @param header_value this is the content, it should be allocated
561 with malloc()
562*/
563
564struct mailimap_search_key *
565mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value);
566
567
568/*
569 this function creates a condition structure to match messages with size
570*/
571
572struct mailimap_search_key *
573mailimap_search_key_new_larger(uint32_t sk_larger);
574
575/*
576 this function creates a condition structure to match messages that
577 do not match the given condition
578*/
579
580struct mailimap_search_key *
581mailimap_search_key_new_not(struct mailimap_search_key * sk_not);
582
583/*
584 this function creates a condition structure to match messages that
585 match one of the given conditions
586*/
587
588struct mailimap_search_key *
589mailimap_search_key_new_or(struct mailimap_search_key * sk_or1,
590 struct mailimap_search_key * sk_or2);
591
592/*
593 this function creates a condition structure to match messages
594 with Date field
595*/
596
597struct mailimap_search_key *
598mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore);
599
600/*
601 this function creates a condition structure to match messages
602 with Date field
603*/
604
605struct mailimap_search_key *
606mailimap_search_key_new_senton(struct mailimap_date * sk_senton);
607
608/*
609 this function creates a condition structure to match messages
610 with Date field
611*/
612
613struct mailimap_search_key *
614mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince);
615
616/*
617 this function creates a condition structure to match messages with size
618*/
619
620struct mailimap_search_key *
621mailimap_search_key_new_smaller(uint32_t sk_smaller);
622
623/*
624 this function creates a condition structure to match messages with unique
625 identifier
626*/
627
628struct mailimap_search_key *
629mailimap_search_key_new_uid(struct mailimap_set * sk_uid);
630
631/*
632 this function creates a condition structure to match messages with number
633 or unique identifier (depending whether SEARCH or UID SEARCH is used)
634*/
635
636struct mailimap_search_key *
637mailimap_search_key_new_set(struct mailimap_set * sk_set);
638
639/*
640 this function creates a condition structure to match messages that match
641 all the conditions given in the list
642*/
643
644struct mailimap_search_key *
645mailimap_search_key_new_multiple(clist * sk_multiple);
646
647
648/*
649 same as previous but the list is empty
650*/
651
652struct mailimap_search_key *
653mailimap_search_key_new_multiple_empty(void);
654
655/*
656 this function adds a condition to the condition list
657
658 @return MAILIMAP_NO_ERROR will be returned on success,
659 other code will be returned otherwise
660*/
661
662int
663mailimap_search_key_multiple_add(struct mailimap_search_key * keys,
664 struct mailimap_search_key * key_item);
665
666
667/*
668 this function creates an empty list of flags
669*/
670
671struct mailimap_flag_list *
672mailimap_flag_list_new_empty(void);
673
674/*
675 this function adds a flag to the list of flags
676
677 @return MAILIMAP_NO_ERROR will be returned on success,
678 other code will be returned otherwise
679*/
680
681int mailimap_flag_list_add(struct mailimap_flag_list * flag_list,
682 struct mailimap_flag * f);
683
684/*
685 this function creates a \Answered flag
686*/
687
688struct mailimap_flag * mailimap_flag_new_answered(void);
689
690/*
691 this function creates a \Flagged flag
692*/
693
694struct mailimap_flag * mailimap_flag_new_flagged(void);
695
696/*
697 this function creates a \Deleted flag
698*/
699
700struct mailimap_flag * mailimap_flag_new_deleted(void);
701
702/*
703 this function creates a \Seen flag
704*/
705
706struct mailimap_flag * mailimap_flag_new_seen(void);
707
708/*
709 this function creates a \Draft flag
710*/
711
712struct mailimap_flag * mailimap_flag_new_draft(void);
713
714/*
715 this function creates a keyword flag
716
717 @param flag_keyword this should be allocated with malloc()
718*/
719
720struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword);
721
722
723/*
724 this function creates an extension flag
725
726 @param flag_extension this should be allocated with malloc()
727*/
728
729struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension);
730
731/*
732 this function creates an empty list of status attributes
733*/
734
735struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void);
736
737/*
738 this function adds status attributes to the list
739
740 @return MAILIMAP_NO_ERROR will be returned on success,
741 other code will be returned otherwise
742*/
743
744int
745mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list,
746 int status_att);
747
748/* return mailimap_section_part from a given mailimap_body */
749
750int mailimap_get_section_part_from_body(struct mailimap_body * root_part,
751 struct mailimap_body * part,
752 struct mailimap_section_part ** result);
753
754#ifdef __cplusplus
755}
756#endif
757
758#endif
diff --git a/libetpan/src/low-level/imf/TODO b/libetpan/src/low-level/imf/TODO
new file mode 100644
index 0000000..f36f55f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/TODO
@@ -0,0 +1,12 @@
1- define a EP_parserstate_s
2- remove clist usage
3- add a errorcode to string function
4- error codes are EP_errornr_s
5- prefix everything with EP_
6- mailimf_dot_atom_text_free
7- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr)
8- in fact that data structure should then also contain a
9 'dynamically' allocated flag
10
11- RFC 822 : test the examples
12- RFC 2822 : obsolete syntax
diff --git a/libetpan/src/low-level/imf/mailimf.c b/libetpan/src/low-level/imf/mailimf.c
new file mode 100644
index 0000000..333767a
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf.c
@@ -0,0 +1,7585 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf.h"
37
38/*
39 RFC 2822
40
41 RFC 2821 ...
42 A message-originating SMTP system SHOULD NOT send a message that
43 already contains a Return-path header. SMTP servers performing a
44 relay function MUST NOT inspect the message data, and especially not
45 to the extent needed to determine if Return-path headers are present.
46 SMTP servers making final delivery MAY remove Return-path headers
47 before adding their own.
48*/
49
50#include <ctype.h>
51#include "mmapstring.h"
52#include <stdlib.h>
53#include <string.h>
54
55#ifndef TRUE
56#define TRUE 1
57#endif
58
59#ifndef FALSE
60#define FALSE 0
61#endif
62
63
64
65
66
67
68
69static inline int is_dtext(char ch);
70
71static int mailimf_quoted_pair_parse(const char * message, size_t length,
72 size_t * index, char * result);
73
74static int mailimf_ccontent_parse(const char * message, size_t length,
75 size_t * index);
76
77static int
78mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
79 size_t * index);
80
81static inline int mailimf_comment_parse(const char * message, size_t length,
82 size_t * index);
83
84static int mailimf_qcontent_parse(const char * message, size_t length,
85 size_t * index, char * ch);
86
87static int mailimf_phrase_parse(const char * message, size_t length,
88 size_t * index, char ** result);
89
90static int mailimf_unstructured_parse(const char * message, size_t length,
91 size_t * index, char ** result);
92
93static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
94 size_t * index);
95
96static int mailimf_day_of_week_parse(const char * message, size_t length,
97 size_t * index, int * result);
98
99static int mailimf_day_name_parse(const char * message, size_t length,
100 size_t * index, int * result);
101
102static int mailimf_date_parse(const char * message, size_t length,
103 size_t * index,
104 int * pday, int * pmonth, int * pyear);
105
106static int mailimf_year_parse(const char * message, size_t length,
107 size_t * index, int * result);
108
109static int mailimf_month_parse(const char * message, size_t length,
110 size_t * index, int * result);
111
112static int mailimf_month_name_parse(const char * message, size_t length,
113 size_t * index, int * result);
114
115static int mailimf_day_parse(const char * message, size_t length,
116 size_t * index, int * result);
117
118static int mailimf_time_parse(const char * message, size_t length,
119 size_t * index,
120 int * phour, int * pmin,
121 int * psec,
122 int * zone);
123static int mailimf_time_of_day_parse(const char * message, size_t length,
124 size_t * index,
125 int * phour, int * pmin,
126 int * psec);
127
128static int mailimf_hour_parse(const char * message, size_t length,
129 size_t * index, int * result);
130
131static int mailimf_minute_parse(const char * message, size_t length,
132 size_t * index, int * result);
133
134static int mailimf_second_parse(const char * message, size_t length,
135 size_t * index, int * result);
136
137static int mailimf_zone_parse(const char * message, size_t length,
138 size_t * index, int * result);
139
140static int mailimf_name_addr_parse(const char * message, size_t length,
141 size_t * index,
142 char ** pdisplay_name,
143 char ** pangle_addr);
144
145static int mailimf_angle_addr_parse(const char * message, size_t length,
146 size_t * index, char ** result);
147
148static int mailimf_group_parse(const char * message, size_t length,
149 size_t * index,
150 struct mailimf_group ** result);
151
152static int mailimf_display_name_parse(const char * message, size_t length,
153 size_t * index, char ** result);
154
155static int mailimf_addr_spec_parse(const char * message, size_t length,
156 size_t * index,
157 char ** address);
158
159#if 0
160static int mailimf_local_part_parse(const char * message, size_t length,
161 size_t * index,
162 char ** result);
163
164static int mailimf_domain_parse(const char * message, size_t length,
165 size_t * index,
166 char ** result);
167#endif
168
169#if 0
170static int mailimf_domain_literal_parse(const char * message, size_t length,
171 size_t * index, char ** result);
172#endif
173
174#if 0
175static int mailimf_dcontent_parse(const char * message, size_t length,
176 size_t * index, char * result);
177#endif
178
179static int
180mailimf_orig_date_parse(const char * message, size_t length,
181 size_t * index, struct mailimf_orig_date ** result);
182
183static int
184mailimf_from_parse(const char * message, size_t length,
185 size_t * index, struct mailimf_from ** result);
186
187static int
188mailimf_sender_parse(const char * message, size_t length,
189 size_t * index, struct mailimf_sender ** result);
190
191static int
192mailimf_reply_to_parse(const char * message, size_t length,
193 size_t * index, struct mailimf_reply_to ** result);
194
195static int
196mailimf_to_parse(const char * message, size_t length,
197 size_t * index, struct mailimf_to ** result);
198
199static int
200mailimf_cc_parse(const char * message, size_t length,
201 size_t * index, struct mailimf_cc ** result);
202
203static int
204mailimf_bcc_parse(const char * message, size_t length,
205 size_t * index, struct mailimf_bcc ** result);
206
207static int mailimf_message_id_parse(const char * message, size_t length,
208 size_t * index,
209 struct mailimf_message_id ** result);
210
211static int
212mailimf_in_reply_to_parse(const char * message, size_t length,
213 size_t * index,
214 struct mailimf_in_reply_to ** result);
215
216#if 0
217static int mailimf_references_parse(const char * message, size_t length,
218 size_t * index,
219 struct mailimf_references **
220 result);
221#endif
222
223static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
224 size_t * index,
225 char ** result);
226
227#if 0
228static int mailimf_id_left_parse(const char * message, size_t length,
229 size_t * index, char ** result);
230
231static int mailimf_id_right_parse(const char * message, size_t length,
232 size_t * index, char ** result);
233#endif
234
235#if 0
236static int mailimf_no_fold_quote_parse(const char * message, size_t length,
237 size_t * index, char ** result);
238
239static int mailimf_no_fold_literal_parse(const char * message, size_t length,
240 size_t * index, char ** result);
241#endif
242
243static int mailimf_subject_parse(const char * message, size_t length,
244 size_t * index,
245 struct mailimf_subject ** result);
246
247static int mailimf_comments_parse(const char * message, size_t length,
248 size_t * index,
249 struct mailimf_comments ** result);
250
251static int mailimf_keywords_parse(const char * message, size_t length,
252 size_t * index,
253 struct mailimf_keywords ** result);
254
255static int
256mailimf_resent_date_parse(const char * message, size_t length,
257 size_t * index, struct mailimf_orig_date ** result);
258
259static int
260mailimf_resent_from_parse(const char * message, size_t length,
261 size_t * index, struct mailimf_from ** result);
262
263static int
264mailimf_resent_sender_parse(const char * message, size_t length,
265 size_t * index, struct mailimf_sender ** result);
266
267static int
268mailimf_resent_to_parse(const char * message, size_t length,
269 size_t * index, struct mailimf_to ** result);
270
271static int
272mailimf_resent_cc_parse(const char * message, size_t length,
273 size_t * index, struct mailimf_cc ** result);
274
275static int
276mailimf_resent_bcc_parse(const char * message, size_t length,
277 size_t * index, struct mailimf_bcc ** result);
278
279static int
280mailimf_resent_msg_id_parse(const char * message, size_t length,
281 size_t * index,
282 struct mailimf_message_id ** result);
283
284static int mailimf_return_parse(const char * message, size_t length,
285 size_t * index,
286 struct mailimf_return ** result);
287
288static int
289mailimf_path_parse(const char * message, size_t length,
290 size_t * index, struct mailimf_path ** result);
291
292static int
293mailimf_optional_field_parse(const char * message, size_t length,
294 size_t * index,
295 struct mailimf_optional_field ** result);
296
297static int mailimf_field_name_parse(const char * message, size_t length,
298 size_t * index, char ** result);
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324/* *************************************************************** */
325
326static inline int is_digit(char ch)
327{
328 return (ch >= '0') && (ch <= '9');
329}
330
331static int mailimf_digit_parse(const char * message, size_t length,
332 size_t * index, int * result)
333{
334 size_t cur_token;
335
336 cur_token = * index;
337
338 if (cur_token >= length)
339 return MAILIMF_ERROR_PARSE;
340
341 if (is_digit(message[cur_token])) {
342 * result = message[cur_token] - '0';
343 cur_token ++;
344 * index = cur_token;
345 return MAILIMF_NO_ERROR;
346 }
347 else
348 return MAILIMF_ERROR_PARSE;
349}
350
351int
352mailimf_number_parse(const char * message, size_t length,
353 size_t * index, uint32_t * result)
354{
355 size_t cur_token;
356 int digit;
357 uint32_t number;
358 int parsed;
359 int r;
360
361 cur_token = * index;
362 parsed = FALSE;
363
364 number = 0;
365 while (1) {
366 r = mailimf_digit_parse(message, length, &cur_token, &digit);
367 if (r != MAILIMF_NO_ERROR) {
368 if (r == MAILIMF_ERROR_PARSE)
369 break;
370 else
371 return r;
372 }
373 number *= 10;
374 number += digit;
375 parsed = TRUE;
376 }
377
378 if (!parsed)
379 return MAILIMF_ERROR_PARSE;
380
381 * result = number;
382 * index = cur_token;
383
384 return MAILIMF_NO_ERROR;
385}
386
387int mailimf_char_parse(const char * message, size_t length,
388 size_t * index, char token)
389{
390 size_t cur_token;
391
392 cur_token = * index;
393
394 if (cur_token >= length)
395 return MAILIMF_ERROR_PARSE;
396
397 if (message[cur_token] == token) {
398 cur_token ++;
399 * index = cur_token;
400 return MAILIMF_NO_ERROR;
401 }
402 else
403 return MAILIMF_ERROR_PARSE;
404}
405
406int mailimf_unstrict_char_parse(const char * message, size_t length,
407 size_t * index, char token)
408{
409 size_t cur_token;
410 int r;
411
412 cur_token = * index;
413
414 r = mailimf_cfws_parse(message, length, &cur_token);
415 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
416 return r;
417
418 r = mailimf_char_parse(message, length, &cur_token, token);
419 if (r != MAILIMF_NO_ERROR)
420 return r;
421
422 * index = cur_token;
423
424 return MAILIMF_NO_ERROR;
425}
426
427int
428mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
429 size_t * index, char * token,
430 size_t token_length)
431{
432 size_t cur_token;
433
434 cur_token = * index;
435
436 if (cur_token + token_length - 1 >= length)
437 return MAILIMF_ERROR_PARSE;
438
439 if (strncasecmp(message + cur_token, token, token_length) == 0) {
440 cur_token += token_length;
441 * index = cur_token;
442 return MAILIMF_NO_ERROR;
443 }
444 else
445 return MAILIMF_ERROR_PARSE;
446}
447
448static int mailimf_oparenth_parse(const char * message, size_t length,
449 size_t * index)
450{
451 return mailimf_char_parse(message, length, index, '(');
452}
453
454static int mailimf_cparenth_parse(const char * message, size_t length,
455 size_t * index)
456{
457 return mailimf_char_parse(message, length, index, ')');
458}
459
460static int mailimf_comma_parse(const char * message, size_t length,
461 size_t * index)
462{
463 return mailimf_unstrict_char_parse(message, length, index, ',');
464}
465
466static int mailimf_dquote_parse(const char * message, size_t length,
467 size_t * index)
468{
469 return mailimf_char_parse(message, length, index, '\"');
470}
471
472static int mailimf_colon_parse(const char * message, size_t length,
473 size_t * index)
474{
475 return mailimf_unstrict_char_parse(message, length, index, ':');
476}
477
478static int mailimf_semi_colon_parse(const char * message, size_t length,
479 size_t * index)
480{
481 return mailimf_unstrict_char_parse(message, length, index, ';');
482}
483
484static int mailimf_plus_parse(const char * message, size_t length,
485 size_t * index)
486{
487 return mailimf_unstrict_char_parse(message, length, index, '+');
488}
489
490static int mailimf_minus_parse(const char * message, size_t length,
491 size_t * index)
492{
493 return mailimf_unstrict_char_parse(message, length, index, '-');
494}
495
496static int mailimf_lower_parse(const char * message, size_t length,
497 size_t * index)
498{
499 return mailimf_unstrict_char_parse(message, length, index, '<');
500}
501
502static int mailimf_greater_parse(const char * message, size_t length,
503 size_t * index)
504{
505 return mailimf_unstrict_char_parse(message, length, index, '>');
506}
507
508#if 0
509static int mailimf_obracket_parse(const char * message, size_t length,
510 size_t * index)
511{
512 return mailimf_unstrict_char_parse(message, length, index, '[');
513}
514
515static int mailimf_cbracket_parse(const char * message, size_t length,
516 size_t * index)
517{
518 return mailimf_unstrict_char_parse(message, length, index, ']');
519}
520#endif
521
522static int mailimf_at_sign_parse(const char * message, size_t length,
523 size_t * index)
524{
525 return mailimf_unstrict_char_parse(message, length, index, '@');
526}
527
528static int mailimf_point_parse(const char * message, size_t length,
529 size_t * index)
530{
531 return mailimf_unstrict_char_parse(message, length, index, '.');
532}
533
534int
535mailimf_custom_string_parse(const char * message, size_t length,
536 size_t * index, char ** result,
537 int (* is_custom_char)(char))
538{
539 size_t begin;
540 size_t end;
541 char * gstr;
542
543 begin = * index;
544
545 end = begin;
546
547 if (end >= length)
548 return MAILIMF_ERROR_PARSE;
549
550 while (is_custom_char(message[end])) {
551 end ++;
552 if (end >= length)
553 break;
554 }
555
556 if (end != begin) {
557 /*
558 gstr = strndup(message + begin, end - begin);
559 */
560 gstr = malloc(end - begin + 1);
561 if (gstr == NULL)
562 return MAILIMF_ERROR_MEMORY;
563 strncpy(gstr, message + begin, end - begin);
564 gstr[end - begin] = '\0';
565
566 * index = end;
567 * result = gstr;
568 return MAILIMF_NO_ERROR;
569 }
570 else
571 return MAILIMF_ERROR_PARSE;
572}
573
574
575
576
577
578
579
580typedef int mailimf_struct_parser(const char * message, size_t length,
581 size_t * index, void * result);
582
583typedef int mailimf_struct_destructor(void * result);
584
585
586static int
587mailimf_struct_multiple_parse(const char * message, size_t length,
588 size_t * index, clist ** result,
589 mailimf_struct_parser * parser,
590 mailimf_struct_destructor * destructor)
591{
592 clist * struct_list;
593 size_t cur_token;
594 void * value;
595 int r;
596 int res;
597
598 cur_token = * index;
599
600 r = parser(message, length, &cur_token, &value);
601 if (r != MAILIMF_NO_ERROR) {
602 res = r;
603 goto err;
604 }
605
606 struct_list = clist_new();
607 if (struct_list == NULL) {
608 destructor(value);
609 res = MAILIMF_ERROR_MEMORY;
610 goto err;
611 }
612
613 r = clist_append(struct_list, value);
614 if (r < 0) {
615 destructor(value);
616 res = MAILIMF_ERROR_MEMORY;
617 goto free;
618 }
619
620 while (1) {
621 r = parser(message, length, &cur_token, &value);
622 if (r != MAILIMF_NO_ERROR) {
623 if (r == MAILIMF_ERROR_PARSE)
624 break;
625 else {
626 res = r;
627 goto free;
628 }
629 }
630 r = clist_append(struct_list, value);
631 if (r < 0) {
632 (* destructor)(value);
633 res = MAILIMF_ERROR_MEMORY;
634 goto free;
635 }
636 }
637
638 * result = struct_list;
639 * index = cur_token;
640
641 return MAILIMF_NO_ERROR;
642
643 free:
644 clist_foreach(struct_list, (clist_func) destructor, NULL);
645 clist_free(struct_list);
646 err:
647 return res;
648}
649
650
651
652static int
653mailimf_struct_list_parse(const char * message, size_t length,
654 size_t * index, clist ** result,
655 char symbol,
656 mailimf_struct_parser * parser,
657 mailimf_struct_destructor * destructor)
658{
659 clist * struct_list;
660 size_t cur_token;
661 void * value;
662 size_t final_token;
663 int r;
664 int res;
665
666 cur_token = * index;
667
668 r = parser(message, length, &cur_token, &value);
669 if (r != MAILIMF_NO_ERROR) {
670 res = r;
671 goto err;
672 }
673
674 struct_list = clist_new();
675 if (struct_list == NULL) {
676 destructor(value);
677 res = MAILIMF_ERROR_MEMORY;
678 goto err;
679 }
680
681 r = clist_append(struct_list, value);
682 if (r < 0) {
683 destructor(value);
684 res = MAILIMF_ERROR_MEMORY;
685 goto free;
686 }
687
688 final_token = cur_token;
689
690 while (1) {
691 r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
692 if (r != MAILIMF_NO_ERROR) {
693 if (r == MAILIMF_ERROR_PARSE)
694 break;
695 else {
696 res = r;
697 goto free;
698 }
699 }
700
701 r = parser(message, length, &cur_token, &value);
702 if (r != MAILIMF_NO_ERROR) {
703 if (r == MAILIMF_ERROR_PARSE)
704 break;
705 else {
706 res = r;
707 goto free;
708 }
709 }
710
711 r = clist_append(struct_list, value);
712 if (r < 0) {
713 destructor(value);
714 res = MAILIMF_ERROR_MEMORY;
715 goto free;
716 }
717
718 final_token = cur_token;
719 }
720
721 * result = struct_list;
722 * index = final_token;
723
724 return MAILIMF_NO_ERROR;
725
726 free:
727 clist_foreach(struct_list, (clist_func) destructor, NULL);
728 clist_free(struct_list);
729 err:
730 return res;
731}
732
733static inline int mailimf_wsp_parse(const char * message, size_t length,
734 size_t * index)
735{
736 size_t cur_token;
737
738 cur_token = * index;
739
740 if (cur_token >= length)
741 return MAILIMF_ERROR_PARSE;
742
743 if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
744 return MAILIMF_ERROR_PARSE;
745
746 cur_token ++;
747 * index = cur_token;
748
749 return MAILIMF_NO_ERROR;
750}
751
752
753int mailimf_crlf_parse(const char * message, size_t length, size_t * index)
754{
755 size_t cur_token;
756 int r;
757
758 cur_token = * index;
759
760 r = mailimf_char_parse(message, length, &cur_token, '\r');
761 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
762 return r;
763
764 r = mailimf_char_parse(message, length, &cur_token, '\n');
765 if (r != MAILIMF_NO_ERROR)
766 return r;
767
768 * index = cur_token;
769 return MAILIMF_NO_ERROR;
770}
771
772static int mailimf_unstrict_crlf_parse(const char * message,
773 size_t length, size_t * index)
774{
775 size_t cur_token;
776 int r;
777
778 cur_token = * index;
779
780 mailimf_cfws_parse(message, length, &cur_token);
781
782 r = mailimf_char_parse(message, length, &cur_token, '\r');
783 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
784 return r;
785
786 r = mailimf_char_parse(message, length, &cur_token, '\n');
787 if (r != MAILIMF_NO_ERROR)
788 return r;
789
790 * index = cur_token;
791 return MAILIMF_NO_ERROR;
792}
793
794/* ************************************************************************ */
795
796
797
798/* RFC 2822 grammar */
799
800/*
801NO-WS-CTL = %d1-8 / ; US-ASCII control characters
802 %d11 / ; that do not include the
803 %d12 / ; carriage return, line feed,
804 %d14-31 / ; and white space characters
805 %d127
806*/
807
808static inline int is_no_ws_ctl(char ch)
809{
810 if ((ch == 9) || (ch == 10) || (ch == 13))
811 return FALSE;
812
813 if (ch == 127)
814 return TRUE;
815
816 return (ch >= 1) && (ch <= 31);
817}
818
819/*
820text = %d1-9 / ; Characters excluding CR and LF
821 %d11 /
822 %d12 /
823 %d14-127 /
824 obs-text
825*/
826
827/*
828specials = "(" / ")" / ; Special characters used in
829 "<" / ">" / ; other parts of the syntax
830 "[" / "]" /
831 ":" / ";" /
832 "@" / "\" /
833 "," / "." /
834 DQUOTE
835*/
836
837/*
838quoted-pair = ("\" text) / obs-qp
839*/
840
841static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
842 size_t * index, char * result)
843{
844 size_t cur_token;
845
846 cur_token = * index;
847
848 if (cur_token + 1 >= length)
849 return MAILIMF_ERROR_PARSE;
850
851 if (message[cur_token] != '\\')
852 return MAILIMF_ERROR_PARSE;
853
854 cur_token ++;
855 * result = message[cur_token];
856 cur_token ++;
857 * index = cur_token;
858
859 return MAILIMF_NO_ERROR;
860}
861
862/*
863FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
864 obs-FWS
865*/
866
867int mailimf_fws_parse(const char * message, size_t length, size_t * index)
868{
869 size_t cur_token;
870 size_t final_token;
871 int fws_1;
872 int fws_2;
873 int fws_3;
874 int r;
875
876 cur_token = * index;
877
878 fws_1 = FALSE;
879 while (1) {
880 r = mailimf_wsp_parse(message, length, &cur_token);
881 if (r != MAILIMF_NO_ERROR) {
882 if (r == MAILIMF_ERROR_PARSE)
883 break;
884 else
885 return r;
886 }
887 fws_1 = TRUE;
888 }
889 final_token = cur_token;
890
891 r = mailimf_crlf_parse(message, length, &cur_token);
892 switch (r) {
893 case MAILIMF_NO_ERROR:
894 fws_2 = TRUE;
895 break;
896 case MAILIMF_ERROR_PARSE:
897 fws_2 = FALSE;
898 break;
899 default:
900 return r;
901 }
902
903 fws_3 = FALSE;
904 if (fws_2) {
905 while (1) {
906 r = mailimf_wsp_parse(message, length, &cur_token);
907 if (r != MAILIMF_NO_ERROR) {
908 if (r == MAILIMF_ERROR_PARSE)
909 break;
910 else
911 return r;
912 }
913 fws_3 = TRUE;
914 }
915 }
916
917 if ((!fws_1) && (!fws_3))
918 return MAILIMF_ERROR_PARSE;
919
920 if (!fws_3)
921 cur_token = final_token;
922
923 * index = cur_token;
924
925 return MAILIMF_NO_ERROR;
926}
927
928
929/*
930ctext = NO-WS-CTL / ; Non white space controls
931
932 %d33-39 / ; The rest of the US-ASCII
933 %d42-91 / ; characters not including "(",
934 %d93-126 ; ")", or "\"
935*/
936
937static inline int is_ctext(char ch)
938{
939 unsigned char uch = (unsigned char) ch;
940
941 if (is_no_ws_ctl(ch))
942 return TRUE;
943
944 if (uch < 33)
945 return FALSE;
946
947 if ((uch == 40) || (uch == 41))
948 return FALSE;
949
950 if (uch == 92)
951 return FALSE;
952
953 if (uch == 127)
954 return FALSE;
955
956 return TRUE;
957}
958
959/*
960ccontent = ctext / quoted-pair / comment
961*/
962
963static inline int mailimf_ccontent_parse(const char * message, size_t length,
964 size_t * index)
965{
966 size_t cur_token;
967 char ch;
968 int r;
969
970 cur_token = * index;
971
972 if (cur_token >= length)
973 return MAILIMF_ERROR_PARSE;
974
975 if (is_ctext(message[cur_token])) {
976 cur_token ++;
977 }
978 else {
979 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
980
981 if (r == MAILIMF_ERROR_PARSE)
982 r = mailimf_comment_parse(message, length, &cur_token);
983
984 if (r == MAILIMF_ERROR_PARSE)
985 return r;
986 }
987
988 * index = cur_token;
989
990 return MAILIMF_NO_ERROR;
991}
992
993/*
994[FWS] ccontent
995*/
996
997static inline int
998mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
999 size_t * index)
1000{
1001 size_t cur_token;
1002 int r;
1003
1004 cur_token = * index;
1005
1006 r = mailimf_fws_parse(message, length, &cur_token);
1007 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1008 return r;
1009
1010 r = mailimf_ccontent_parse(message, length, &cur_token);
1011 if (r != MAILIMF_NO_ERROR)
1012 return r;
1013
1014 * index = cur_token;
1015
1016 return MAILIMF_NO_ERROR;
1017}
1018
1019/*
1020comment = "(" *([FWS] ccontent) [FWS] ")"
1021*/
1022
1023static inline int mailimf_comment_parse(const char * message, size_t length,
1024 size_t * index)
1025{
1026 size_t cur_token;
1027 int r;
1028
1029 cur_token = * index;
1030
1031 r = mailimf_oparenth_parse(message, length, &cur_token);
1032 if (r != MAILIMF_NO_ERROR)
1033 return r;
1034
1035 while (1) {
1036 r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
1037 if (r != MAILIMF_NO_ERROR) {
1038 if (r == MAILIMF_ERROR_PARSE)
1039 break;
1040 else
1041 return r;
1042 }
1043 }
1044
1045 r = mailimf_fws_parse(message, length, &cur_token);
1046 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1047 return r;
1048
1049 r = mailimf_cparenth_parse(message, length, &cur_token);
1050 if (r != MAILIMF_NO_ERROR)
1051 return r;
1052
1053 * index = cur_token;
1054
1055 return MAILIMF_NO_ERROR;
1056}
1057
1058/*
1059[FWS] comment
1060*/
1061
1062static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
1063 size_t * index)
1064{
1065 size_t cur_token;
1066 int r;
1067
1068 cur_token = * index;
1069
1070 r = mailimf_fws_parse(message, length, &cur_token);
1071 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1072 return r;
1073
1074 r = mailimf_comment_parse(message, length, &cur_token);
1075 if (r != MAILIMF_NO_ERROR)
1076 return r;
1077
1078 * index = cur_token;
1079
1080 return MAILIMF_NO_ERROR;
1081}
1082
1083/*
1084CFWS = *([FWS] comment) (([FWS] comment) / FWS)
1085*/
1086
1087int mailimf_cfws_parse(const char * message, size_t length,
1088 size_t * index)
1089{
1090 size_t cur_token;
1091 int has_comment;
1092 int r;
1093
1094 cur_token = * index;
1095
1096 has_comment = FALSE;
1097 while (1) {
1098 r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
1099 if (r != MAILIMF_NO_ERROR) {
1100 if (r == MAILIMF_ERROR_PARSE)
1101 break;
1102 else
1103 return r;
1104 }
1105 has_comment = TRUE;
1106 }
1107
1108 if (!has_comment) {
1109 r = mailimf_fws_parse(message, length, &cur_token);
1110 if (r != MAILIMF_NO_ERROR)
1111 return r;
1112 }
1113
1114 * index = cur_token;
1115
1116 return MAILIMF_NO_ERROR;
1117}
1118
1119/*
1120atext = ALPHA / DIGIT / ; Any character except controls,
1121 "!" / "#" / ; SP, and specials.
1122 "$" / "%" / ; Used for atoms
1123 "&" / "'" /
1124 "*" / "+" /
1125 "-" / "/" /
1126 "=" / "?" /
1127 "^" / "_" /
1128 "`" / "{" /
1129 "|" / "}" /
1130 "~"
1131*/
1132
1133static inline int is_atext(char ch)
1134{
1135 switch (ch) {
1136 case ' ':
1137 case '\t':
1138 case '\n':
1139 case '\r':
1140#if 0
1141 case '(':
1142 case ')':
1143#endif
1144 case '<':
1145 case '>':
1146#if 0
1147 case '@':
1148#endif
1149 case ',':
1150 case '"':
1151 case ':':
1152 case ';':
1153 return FALSE;
1154 default:
1155 return TRUE;
1156 }
1157}
1158
1159/*
1160atom = [CFWS] 1*atext [CFWS]
1161*/
1162
1163int mailimf_atom_parse(const char * message, size_t length,
1164 size_t * index, char ** result)
1165{
1166 size_t cur_token;
1167 int r;
1168 int res;
1169 char * atom;
1170 size_t end;
1171
1172 cur_token = * index;
1173
1174 r = mailimf_cfws_parse(message, length, &cur_token);
1175 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1176 res = r;
1177 goto err;
1178 }
1179
1180 end = cur_token;
1181 if (end >= length) {
1182 res = MAILIMF_ERROR_PARSE;
1183 goto err;
1184 }
1185
1186 while (is_atext(message[end])) {
1187 end ++;
1188 if (end >= length)
1189 break;
1190 }
1191 if (end == cur_token) {
1192 res = MAILIMF_ERROR_PARSE;
1193 goto err;
1194 }
1195
1196 atom = malloc(end - cur_token + 1);
1197 if (atom == NULL) {
1198 res = MAILIMF_ERROR_MEMORY;
1199 goto err;
1200 }
1201 strncpy(atom, message + cur_token, end - cur_token);
1202 atom[end - cur_token] = '\0';
1203
1204 cur_token = end;
1205
1206 * index = cur_token;
1207 * result = atom;
1208
1209 return MAILIMF_NO_ERROR;
1210
1211 err:
1212 return res;
1213}
1214
1215int mailimf_fws_atom_parse(const char * message, size_t length,
1216 size_t * index, char ** result)
1217{
1218 size_t cur_token;
1219 int r;
1220 int res;
1221 char * atom;
1222 size_t end;
1223
1224 cur_token = * index;
1225
1226 r = mailimf_fws_parse(message, length, &cur_token);
1227 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1228 res = r;
1229 goto err;
1230 }
1231
1232 end = cur_token;
1233 if (end >= length) {
1234 res = MAILIMF_ERROR_PARSE;
1235 goto err;
1236 }
1237
1238 while (is_atext(message[end])) {
1239 end ++;
1240 if (end >= length)
1241 break;
1242 }
1243 if (end == cur_token) {
1244 res = MAILIMF_ERROR_PARSE;
1245 goto err;
1246 }
1247
1248 atom = malloc(end - cur_token + 1);
1249 if (atom == NULL) {
1250 res = MAILIMF_ERROR_MEMORY;
1251 goto err;
1252 }
1253 strncpy(atom, message + cur_token, end - cur_token);
1254 atom[end - cur_token] = '\0';
1255
1256 cur_token = end;
1257
1258 * index = cur_token;
1259 * result = atom;
1260
1261 return MAILIMF_NO_ERROR;
1262
1263 err:
1264 return res;
1265}
1266
1267/*
1268dot-atom = [CFWS] dot-atom-text [CFWS]
1269*/
1270
1271#if 0
1272static int mailimf_dot_atom_parse(const char * message, size_t length,
1273 size_t * index, char ** result)
1274{
1275 return mailimf_atom_parse(message, length, index, result);
1276}
1277#endif
1278
1279/*
1280dot-atom-text = 1*atext *("." 1*atext)
1281*/
1282
1283#if 0
1284static int
1285mailimf_dot_atom_text_parse(const char * message, size_t length,
1286 size_t * index, char ** result)
1287{
1288 return mailimf_atom_parse(message, length, index, result);
1289}
1290#endif
1291
1292/*
1293qtext = NO-WS-CTL / ; Non white space controls
1294
1295 %d33 / ; The rest of the US-ASCII
1296 %d35-91 / ; characters not including "\"
1297 %d93-126 ; or the quote character
1298*/
1299
1300static inline int is_qtext(char ch)
1301{
1302 unsigned char uch = (unsigned char) ch;
1303
1304 if (is_no_ws_ctl(ch))
1305 return TRUE;
1306
1307 if (uch < 33)
1308 return FALSE;
1309
1310 if (uch == 34)
1311 return FALSE;
1312
1313 if (uch == 92)
1314 return FALSE;
1315
1316 if (uch == 127)
1317 return FALSE;
1318
1319 return TRUE;
1320}
1321
1322/*
1323qcontent = qtext / quoted-pair
1324*/
1325
1326static int mailimf_qcontent_parse(const char * message, size_t length,
1327 size_t * index, char * result)
1328{
1329 size_t cur_token;
1330 char ch;
1331 int r;
1332
1333 cur_token = * index;
1334
1335 if (cur_token >= length)
1336 return MAILIMF_ERROR_PARSE;
1337
1338 if (is_qtext(message[cur_token])) {
1339 ch = message[cur_token];
1340 cur_token ++;
1341 }
1342 else {
1343 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
1344
1345 if (r != MAILIMF_NO_ERROR)
1346 return r;
1347 }
1348
1349 * result = ch;
1350 * index = cur_token;
1351
1352 return MAILIMF_NO_ERROR;
1353}
1354
1355/*
1356quoted-string = [CFWS]
1357 DQUOTE *([FWS] qcontent) [FWS] DQUOTE
1358 [CFWS]
1359*/
1360
1361int mailimf_quoted_string_parse(const char * message, size_t length,
1362 size_t * index, char ** result)
1363{
1364 size_t cur_token;
1365 MMAPString * gstr;
1366 char ch;
1367 char * str;
1368 int r;
1369 int res;
1370
1371 cur_token = * index;
1372
1373 r = mailimf_cfws_parse(message, length, &cur_token);
1374 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1375 res = r;
1376 goto err;
1377 }
1378
1379 r = mailimf_dquote_parse(message, length, &cur_token);
1380 if (r != MAILIMF_NO_ERROR) {
1381 res = r;
1382 goto err;
1383 }
1384
1385 gstr = mmap_string_new("");
1386 if (gstr == NULL) {
1387 res = MAILIMF_ERROR_MEMORY;
1388 goto err;
1389 }
1390
1391#if 0
1392 if (mmap_string_append_c(gstr, '\"') == NULL) {
1393 res = MAILIMF_ERROR_MEMORY;
1394 goto free_gstr;
1395 }
1396#endif
1397
1398 while (1) {
1399 r = mailimf_fws_parse(message, length, &cur_token);
1400 if (r == MAILIMF_NO_ERROR) {
1401 if (mmap_string_append_c(gstr, ' ') == NULL) {
1402 res = MAILIMF_ERROR_MEMORY;
1403 goto free_gstr;
1404 }
1405 }
1406 else if (r != MAILIMF_ERROR_PARSE) {
1407 res = r;
1408 goto free_gstr;
1409 }
1410
1411 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1412 if (r == MAILIMF_NO_ERROR) {
1413 if (mmap_string_append_c(gstr, ch) == NULL) {
1414 res = MAILIMF_ERROR_MEMORY;
1415 goto free_gstr;
1416 }
1417 }
1418 else if (r == MAILIMF_ERROR_PARSE)
1419 break;
1420 else {
1421 res = r;
1422 goto free_gstr;
1423 }
1424 }
1425
1426 r = mailimf_dquote_parse(message, length, &cur_token);
1427 if (r != MAILIMF_NO_ERROR) {
1428 res = r;
1429 goto free_gstr;
1430 }
1431
1432#if 0
1433 if (mmap_string_append_c(gstr, '\"') == NULL) {
1434 res = MAILIMF_ERROR_MEMORY;
1435 goto free_gstr;
1436 }
1437#endif
1438
1439 str = strdup(gstr->str);
1440 if (str == NULL) {
1441 res = MAILIMF_ERROR_MEMORY;
1442 goto free_gstr;
1443 }
1444 mmap_string_free(gstr);
1445
1446 * index = cur_token;
1447 * result = str;
1448
1449 return MAILIMF_NO_ERROR;
1450
1451 free_gstr:
1452 mmap_string_free(gstr);
1453 err:
1454 return res;
1455}
1456
1457int mailimf_fws_quoted_string_parse(const char * message, size_t length,
1458 size_t * index, char ** result)
1459{
1460 size_t cur_token;
1461 MMAPString * gstr;
1462 char ch;
1463 char * str;
1464 int r;
1465 int res;
1466
1467 cur_token = * index;
1468
1469 r = mailimf_fws_parse(message, length, &cur_token);
1470 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1471 res = r;
1472 goto err;
1473 }
1474
1475 r = mailimf_dquote_parse(message, length, &cur_token);
1476 if (r != MAILIMF_NO_ERROR) {
1477 res = r;
1478 goto err;
1479 }
1480
1481 gstr = mmap_string_new("");
1482 if (gstr == NULL) {
1483 res = MAILIMF_ERROR_MEMORY;
1484 goto err;
1485 }
1486
1487#if 0
1488 if (mmap_string_append_c(gstr, '\"') == NULL) {
1489 res = MAILIMF_ERROR_MEMORY;
1490 goto free_gstr;
1491 }
1492#endif
1493
1494 while (1) {
1495 r = mailimf_fws_parse(message, length, &cur_token);
1496 if (r == MAILIMF_NO_ERROR) {
1497 if (mmap_string_append_c(gstr, ' ') == NULL) {
1498 res = MAILIMF_ERROR_MEMORY;
1499 goto free_gstr;
1500 }
1501 }
1502 else if (r != MAILIMF_ERROR_PARSE) {
1503 res = r;
1504 goto free_gstr;
1505 }
1506
1507 r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
1508 if (r == MAILIMF_NO_ERROR) {
1509 if (mmap_string_append_c(gstr, ch) == NULL) {
1510 res = MAILIMF_ERROR_MEMORY;
1511 goto free_gstr;
1512 }
1513 }
1514 else if (r == MAILIMF_ERROR_PARSE)
1515 break;
1516 else {
1517 res = r;
1518 goto free_gstr;
1519 }
1520 }
1521
1522 r = mailimf_dquote_parse(message, length, &cur_token);
1523 if (r != MAILIMF_NO_ERROR) {
1524 res = r;
1525 goto free_gstr;
1526 }
1527
1528#if 0
1529 if (mmap_string_append_c(gstr, '\"') == NULL) {
1530 res = MAILIMF_ERROR_MEMORY;
1531 goto free_gstr;
1532 }
1533#endif
1534
1535 str = strdup(gstr->str);
1536 if (str == NULL) {
1537 res = MAILIMF_ERROR_MEMORY;
1538 goto free_gstr;
1539 }
1540 mmap_string_free(gstr);
1541
1542 * index = cur_token;
1543 * result = str;
1544
1545 return MAILIMF_NO_ERROR;
1546
1547 free_gstr:
1548 mmap_string_free(gstr);
1549 err:
1550 return res;
1551}
1552
1553/*
1554word = atom / quoted-string
1555*/
1556
1557int mailimf_word_parse(const char * message, size_t length,
1558 size_t * index, char ** result)
1559{
1560 size_t cur_token;
1561 char * word;
1562 int r;
1563
1564 cur_token = * index;
1565
1566 r = mailimf_atom_parse(message, length, &cur_token, &word);
1567
1568 if (r == MAILIMF_ERROR_PARSE)
1569 r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
1570
1571 if (r != MAILIMF_NO_ERROR)
1572 return r;
1573
1574 * result = word;
1575 * index = cur_token;
1576
1577 return MAILIMF_NO_ERROR;
1578}
1579
1580int mailimf_fws_word_parse(const char * message, size_t length,
1581 size_t * index, char ** result)
1582{
1583 size_t cur_token;
1584 char * word;
1585 int r;
1586
1587 cur_token = * index;
1588
1589 r = mailimf_fws_atom_parse(message, length, &cur_token, &word);
1590
1591 if (r == MAILIMF_ERROR_PARSE)
1592 r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
1593
1594 if (r != MAILIMF_NO_ERROR)
1595 return r;
1596
1597 * result = word;
1598 * index = cur_token;
1599
1600 return MAILIMF_NO_ERROR;
1601}
1602
1603/*
1604phrase = 1*word / obs-phrase
1605*/
1606
1607static int mailimf_phrase_parse(const char * message, size_t length,
1608 size_t * index, char ** result)
1609{
1610 MMAPString * gphrase;
1611 char * word;
1612 int first;
1613 size_t cur_token;
1614 int r;
1615 int res;
1616 char * str;
1617
1618 cur_token = * index;
1619
1620 gphrase = mmap_string_new("");
1621 if (gphrase == NULL) {
1622 res = MAILIMF_ERROR_MEMORY;
1623 goto err;
1624 }
1625
1626 first = TRUE;
1627
1628 while (1) {
1629 r = mailimf_fws_word_parse(message, length, &cur_token, &word);
1630 if (r == MAILIMF_NO_ERROR) {
1631 if (!first) {
1632 if (mmap_string_append_c(gphrase, ' ') == NULL) {
1633 mailimf_word_free(word);
1634 res = MAILIMF_ERROR_MEMORY;
1635 goto free;
1636 }
1637 }
1638 if (mmap_string_append(gphrase, word) == NULL) {
1639 mailimf_word_free(word);
1640 res = MAILIMF_ERROR_MEMORY;
1641 goto free;
1642 }
1643 mailimf_word_free(word);
1644 first = FALSE;
1645 }
1646 else if (r == MAILIMF_ERROR_PARSE)
1647 break;
1648 else {
1649 res = r;
1650 goto free;
1651 }
1652 }
1653
1654 if (first) {
1655 res = MAILIMF_ERROR_PARSE;
1656 goto free;
1657 }
1658
1659 str = strdup(gphrase->str);
1660 if (str == NULL) {
1661 res = MAILIMF_ERROR_MEMORY;
1662 goto free;
1663 }
1664 mmap_string_free(gphrase);
1665
1666 * result = str;
1667 * index = cur_token;
1668
1669 return MAILIMF_NO_ERROR;
1670
1671 free:
1672 mmap_string_free(gphrase);
1673 err:
1674 return res;
1675}
1676
1677/*
1678utext = NO-WS-CTL / ; Non white space controls
1679 %d33-126 / ; The rest of US-ASCII
1680 obs-utext
1681
1682added : WSP
1683*/
1684
1685enum {
1686 UNSTRUCTURED_START,
1687 UNSTRUCTURED_CR,
1688 UNSTRUCTURED_LF,
1689 UNSTRUCTURED_WSP,
1690 UNSTRUCTURED_OUT
1691};
1692
1693static int mailimf_unstructured_parse(const char * message, size_t length,
1694 size_t * index, char ** result)
1695{
1696 size_t cur_token;
1697 int state;
1698 size_t begin;
1699 size_t terminal;
1700 char * str;
1701
1702 cur_token = * index;
1703
1704
1705 while (1) {
1706 int r;
1707
1708 r = mailimf_wsp_parse(message, length, &cur_token);
1709 if (r == MAILIMF_NO_ERROR) {
1710 /* do nothing */
1711 }
1712 else if (r == MAILIMF_ERROR_PARSE)
1713 break;
1714 else {
1715 return r;
1716 }
1717 }
1718
1719 state = UNSTRUCTURED_START;
1720 begin = cur_token;
1721 terminal = cur_token;
1722
1723 while (state != UNSTRUCTURED_OUT) {
1724
1725 switch(state) {
1726 case UNSTRUCTURED_START:
1727 if (cur_token >= length)
1728 return MAILIMF_ERROR_PARSE;
1729
1730 terminal = cur_token;
1731 switch(message[cur_token]) {
1732 case '\r':
1733 state = UNSTRUCTURED_CR;
1734 break;
1735 case '\n':
1736 state = UNSTRUCTURED_LF;
1737 break;
1738 default:
1739 state = UNSTRUCTURED_START;
1740 break;
1741 }
1742 break;
1743 case UNSTRUCTURED_CR:
1744 if (cur_token >= length)
1745 return MAILIMF_ERROR_PARSE;
1746
1747 switch(message[cur_token]) {
1748 case '\n':
1749 state = UNSTRUCTURED_LF;
1750 break;
1751 default:
1752 state = UNSTRUCTURED_START;
1753 break;
1754 }
1755 break;
1756
1757 case UNSTRUCTURED_LF:
1758 if (cur_token >= length) {
1759 state = UNSTRUCTURED_OUT;
1760 break;
1761 }
1762
1763 switch(message[cur_token]) {
1764 case '\t':
1765 case ' ':
1766 state = UNSTRUCTURED_WSP;
1767 break;
1768 default:
1769 state = UNSTRUCTURED_OUT;
1770 break;
1771 }
1772 break;
1773 case UNSTRUCTURED_WSP:
1774 if (cur_token >= length)
1775 return MAILIMF_ERROR_PARSE;
1776
1777 switch(message[cur_token]) {
1778 case '\r':
1779 state = UNSTRUCTURED_CR;
1780 break;
1781 case '\n':
1782 state = UNSTRUCTURED_LF;
1783 break;
1784 default:
1785 state = UNSTRUCTURED_START;
1786 break;
1787 }
1788 break;
1789 }
1790
1791 cur_token ++;
1792 }
1793
1794 str = malloc(terminal - begin + 1);
1795 if (str == NULL)
1796 return MAILIMF_ERROR_MEMORY;
1797 strncpy(str, message + begin, terminal - begin);
1798 str[terminal - begin] = '\0';
1799
1800 * index = terminal;
1801 * result = str;
1802
1803 return MAILIMF_NO_ERROR;
1804}
1805
1806
1807static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
1808 size_t * index)
1809{
1810 size_t cur_token;
1811 int state;
1812 size_t terminal;
1813
1814 cur_token = * index;
1815
1816 state = UNSTRUCTURED_START;
1817 terminal = cur_token;
1818
1819 while (state != UNSTRUCTURED_OUT) {
1820
1821 switch(state) {
1822 case UNSTRUCTURED_START:
1823 if (cur_token >= length)
1824 return MAILIMF_ERROR_PARSE;
1825 terminal = cur_token;
1826 switch(message[cur_token]) {
1827 case '\r':
1828 state = UNSTRUCTURED_CR;
1829 break;
1830 case '\n':
1831 state = UNSTRUCTURED_LF;
1832 break;
1833 default:
1834 state = UNSTRUCTURED_START;
1835 break;
1836 }
1837 break;
1838 case UNSTRUCTURED_CR:
1839 if (cur_token >= length)
1840 return MAILIMF_ERROR_PARSE;
1841 switch(message[cur_token]) {
1842 case '\n':
1843 state = UNSTRUCTURED_LF;
1844 break;
1845 default:
1846 state = UNSTRUCTURED_START;
1847 break;
1848 }
1849 break;
1850 case UNSTRUCTURED_LF:
1851 if (cur_token >= length) {
1852 state = UNSTRUCTURED_OUT;
1853 break;
1854 }
1855 switch(message[cur_token]) {
1856 case '\t':
1857 case ' ':
1858 state = UNSTRUCTURED_WSP;
1859 break;
1860 default:
1861 state = UNSTRUCTURED_OUT;
1862 break;
1863 }
1864 break;
1865 case UNSTRUCTURED_WSP:
1866 if (cur_token >= length)
1867 return MAILIMF_ERROR_PARSE;
1868 switch(message[cur_token]) {
1869 case '\r':
1870 state = UNSTRUCTURED_CR;
1871 break;
1872 case '\n':
1873 state = UNSTRUCTURED_LF;
1874 break;
1875 default:
1876 state = UNSTRUCTURED_START;
1877 break;
1878 }
1879 break;
1880 }
1881
1882 cur_token ++;
1883 }
1884
1885 * index = terminal;
1886
1887 return MAILIMF_NO_ERROR;
1888}
1889
1890
1891int mailimf_ignore_field_parse(const char * message, size_t length,
1892 size_t * index)
1893{
1894 int has_field;
1895 size_t cur_token;
1896 int state;
1897 size_t terminal;
1898
1899 has_field = FALSE;
1900 cur_token = * index;
1901
1902 terminal = cur_token;
1903 state = UNSTRUCTURED_START;
1904
1905 /* check if this is not a beginning CRLF */
1906
1907 if (cur_token >= length)
1908 return MAILIMF_ERROR_PARSE;
1909
1910 switch (message[cur_token]) {
1911 case '\r':
1912 return MAILIMF_ERROR_PARSE;
1913 case '\n':
1914 return MAILIMF_ERROR_PARSE;
1915 }
1916
1917 while (state != UNSTRUCTURED_OUT) {
1918
1919 switch(state) {
1920 case UNSTRUCTURED_START:
1921 if (cur_token >= length)
1922 return MAILIMF_ERROR_PARSE;
1923
1924 switch(message[cur_token]) {
1925 case '\r':
1926 state = UNSTRUCTURED_CR;
1927 break;
1928 case '\n':
1929 state = UNSTRUCTURED_LF;
1930 break;
1931 case ':':
1932 has_field = TRUE;
1933 state = UNSTRUCTURED_START;
1934 break;
1935 default:
1936 state = UNSTRUCTURED_START;
1937 break;
1938 }
1939 break;
1940 case UNSTRUCTURED_CR:
1941 if (cur_token >= length)
1942 return MAILIMF_ERROR_PARSE;
1943
1944 switch(message[cur_token]) {
1945 case '\n':
1946 state = UNSTRUCTURED_LF;
1947 break;
1948 case ':':
1949 has_field = TRUE;
1950 state = UNSTRUCTURED_START;
1951 break;
1952 default:
1953 state = UNSTRUCTURED_START;
1954 break;
1955 }
1956 break;
1957 case UNSTRUCTURED_LF:
1958 if (cur_token >= length) {
1959 terminal = cur_token;
1960 state = UNSTRUCTURED_OUT;
1961 break;
1962 }
1963
1964 switch(message[cur_token]) {
1965 case '\t':
1966 case ' ':
1967 state = UNSTRUCTURED_WSP;
1968 break;
1969 default:
1970 terminal = cur_token;
1971 state = UNSTRUCTURED_OUT;
1972 break;
1973 }
1974 break;
1975 case UNSTRUCTURED_WSP:
1976 if (cur_token >= length)
1977 return MAILIMF_ERROR_PARSE;
1978
1979 switch(message[cur_token]) {
1980 case '\r':
1981 state = UNSTRUCTURED_CR;
1982 break;
1983 case '\n':
1984 state = UNSTRUCTURED_LF;
1985 break;
1986 case ':':
1987 has_field = TRUE;
1988 state = UNSTRUCTURED_START;
1989 break;
1990 default:
1991 state = UNSTRUCTURED_START;
1992 break;
1993 }
1994 break;
1995 }
1996
1997 cur_token ++;
1998 }
1999
2000 if (!has_field)
2001 return MAILIMF_ERROR_PARSE;
2002
2003 * index = terminal;
2004
2005 return MAILIMF_NO_ERROR;
2006}
2007
2008
2009/*
2010date-time = [ day-of-week "," ] date FWS time [CFWS]
2011*/
2012
2013int mailimf_date_time_parse(const char * message, size_t length,
2014 size_t * index,
2015 struct mailimf_date_time ** result)
2016{
2017 size_t cur_token;
2018 int day_of_week;
2019 struct mailimf_date_time * date_time;
2020 int day;
2021 int month;
2022 int year;
2023 int hour;
2024 int min;
2025 int sec;
2026 int zone;
2027 int r;
2028
2029 cur_token = * index;
2030
2031 day_of_week = -1;
2032 r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week);
2033 if (r == MAILIMF_NO_ERROR) {
2034 r = mailimf_comma_parse(message, length, &cur_token);
2035 if (r != MAILIMF_NO_ERROR)
2036 return r;
2037 }
2038 else if (r != MAILIMF_ERROR_PARSE)
2039 return r;
2040
2041 r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year);
2042 if (r != MAILIMF_NO_ERROR)
2043 return r;
2044
2045 r = mailimf_fws_parse(message, length, &cur_token);
2046 if (r != MAILIMF_NO_ERROR)
2047 return r;
2048
2049 r = mailimf_time_parse(message, length, &cur_token,
2050 &hour, &min, &sec, &zone);
2051 if (r != MAILIMF_NO_ERROR)
2052 return r;
2053
2054 date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
2055 if (date_time == NULL)
2056 return MAILIMF_ERROR_MEMORY;
2057
2058 * index = cur_token;
2059 * result = date_time;
2060
2061 return MAILIMF_NO_ERROR;
2062}
2063
2064/*
2065day-of-week = ([FWS] day-name) / obs-day-of-week
2066*/
2067
2068static int mailimf_day_of_week_parse(const char * message, size_t length,
2069 size_t * index, int * result)
2070{
2071 size_t cur_token;
2072 int day_of_week;
2073 int r;
2074
2075 cur_token = * index;
2076
2077 r = mailimf_cfws_parse(message, length, &cur_token);
2078 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2079 return r;
2080
2081 r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week);
2082 if (r != MAILIMF_NO_ERROR)
2083 return r;
2084
2085 * index = cur_token;
2086 * result = day_of_week;
2087
2088 return MAILIMF_NO_ERROR;
2089}
2090
2091/*
2092day-name = "Mon" / "Tue" / "Wed" / "Thu" /
2093 "Fri" / "Sat" / "Sun"
2094*/
2095
2096struct mailimf_token_value {
2097 int value;
2098 char * str;
2099};
2100
2101static struct mailimf_token_value day_names[] = {
2102 {1, "Mon"},
2103 {2, "Tue"},
2104 {3, "Wed"},
2105 {4, "Thu"},
2106 {5, "Fri"},
2107 {6, "Sat"},
2108 {7, "Sun"},
2109};
2110
2111enum {
2112 DAY_NAME_START,
2113 DAY_NAME_T,
2114 DAY_NAME_S
2115};
2116
2117static int guess_day_name(const char * message, size_t length, size_t index)
2118{
2119 int state;
2120
2121 state = DAY_NAME_START;
2122
2123 while (1) {
2124
2125 if (index >= length)
2126 return -1;
2127
2128 switch(state) {
2129 case DAY_NAME_START:
2130 switch((char) toupper((unsigned char) message[index])) {
2131 case 'M': /* Mon */
2132 return 1;
2133 break;
2134 case 'T': /* Tue Thu */
2135 state = DAY_NAME_T;
2136 break;
2137 case 'W': /* Wed */
2138 return 3;
2139 case 'F':
2140 return 5;
2141 case 'S': /* Sat Sun */
2142 state = DAY_NAME_S;
2143 break;
2144 default:
2145 return -1;
2146 }
2147 break;
2148 case DAY_NAME_T:
2149 switch((char) toupper((unsigned char) message[index])) {
2150 case 'U':
2151 return 2;
2152 case 'H':
2153 return 4;
2154 default:
2155 return -1;
2156 }
2157 break;
2158 case DAY_NAME_S:
2159 switch((char) toupper((unsigned char) message[index])) {
2160 case 'A':
2161 return 6;
2162 case 'U':
2163 return 7;
2164 default:
2165 return -1;
2166 }
2167 break;
2168 }
2169
2170 index ++;
2171 }
2172}
2173
2174static int mailimf_day_name_parse(const char * message, size_t length,
2175 size_t * index, int * result)
2176{
2177 size_t cur_token;
2178 int day_of_week;
2179 int guessed_day;
2180 int r;
2181
2182 cur_token = * index;
2183
2184 guessed_day = guess_day_name(message, length, cur_token);
2185 if (guessed_day == -1)
2186 return MAILIMF_ERROR_PARSE;
2187
2188 r = mailimf_token_case_insensitive_parse(message, length,
2189 &cur_token,
2190 day_names[guessed_day - 1].str);
2191 if (r != MAILIMF_NO_ERROR)
2192 return r;
2193
2194 day_of_week = guessed_day;
2195
2196 * result = day_of_week;
2197 * index = cur_token;
2198
2199 return MAILIMF_NO_ERROR;
2200}
2201
2202/*
2203date = day month year
2204*/
2205
2206static int mailimf_date_parse(const char * message, size_t length,
2207 size_t * index,
2208 int * pday, int * pmonth, int * pyear)
2209{
2210 size_t cur_token;
2211 int day;
2212 int month;
2213 int year;
2214 int r;
2215
2216 cur_token = * index;
2217
2218 r = mailimf_day_parse(message, length, &cur_token, &day);
2219 if (r != MAILIMF_NO_ERROR)
2220 return r;
2221
2222 r = mailimf_month_parse(message, length, &cur_token, &month);
2223 if (r != MAILIMF_NO_ERROR)
2224 return r;
2225
2226 r = mailimf_year_parse(message, length, &cur_token, &year);
2227 if (r != MAILIMF_NO_ERROR)
2228 return r;
2229
2230 * pday = day;
2231 * pmonth = month;
2232 * pyear = year;
2233
2234 * index = cur_token;
2235
2236 return MAILIMF_NO_ERROR;
2237}
2238
2239/*
2240year = 4*DIGIT / obs-year
2241*/
2242
2243static int mailimf_year_parse(const char * message, size_t length,
2244 size_t * index, int * result)
2245{
2246 uint32_t number;
2247 size_t cur_token;
2248 int r;
2249
2250 cur_token = * index;
2251
2252 r = mailimf_cfws_parse(message, length, &cur_token);
2253 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2254 return r;
2255
2256 r = mailimf_number_parse(message, length, &cur_token, &number);
2257 if (r != MAILIMF_NO_ERROR)
2258 return r;
2259
2260 * index = cur_token;
2261 * result = number;
2262
2263 return MAILIMF_NO_ERROR;
2264}
2265
2266/*
2267month = (FWS month-name FWS) / obs-month
2268*/
2269
2270static int mailimf_month_parse(const char * message, size_t length,
2271 size_t * index, int * result)
2272{
2273 size_t cur_token;
2274 int month;
2275 int r;
2276
2277 cur_token = * index;
2278
2279 r = mailimf_cfws_parse(message, length, &cur_token);
2280 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2281 return r;
2282
2283 r = mailimf_month_name_parse(message, length, &cur_token, &month);
2284 if (r != MAILIMF_NO_ERROR)
2285 return r;
2286
2287 * result = month;
2288 * index = cur_token;
2289
2290 return MAILIMF_NO_ERROR;
2291}
2292
2293/*
2294month-name = "Jan" / "Feb" / "Mar" / "Apr" /
2295 "May" / "Jun" / "Jul" / "Aug" /
2296 "Sep" / "Oct" / "Nov" / "Dec"
2297*/
2298
2299static struct mailimf_token_value month_names[] = {
2300 {1, "Jan"},
2301 {2, "Feb"},
2302 {3, "Mar"},
2303 {4, "Apr"},
2304 {5, "May"},
2305 {6, "Jun"},
2306 {7, "Jul"},
2307 {8, "Aug"},
2308 {9, "Sep"},
2309 {10, "Oct"},
2310 {11, "Nov"},
2311 {12, "Dec"},
2312};
2313
2314enum {
2315 MONTH_START,
2316 MONTH_J,
2317 MONTH_JU,
2318 MONTH_M,
2319 MONTH_MA,
2320 MONTH_A
2321};
2322
2323static int guess_month(const char * message, size_t length, size_t index)
2324{
2325 int state;
2326
2327 state = MONTH_START;
2328
2329 while (1) {
2330
2331 if (index >= length)
2332 return -1;
2333
2334 switch(state) {
2335 case MONTH_START:
2336 switch((char) toupper((unsigned char) message[index])) {
2337 case 'J': /* Jan Jun Jul */
2338 state = MONTH_J;
2339 break;
2340 case 'F': /* Feb */
2341 return 2;
2342 case 'M': /* Mar May */
2343 state = MONTH_M;
2344 break;
2345 case 'A': /* Apr Aug */
2346 state = MONTH_A;
2347 break;
2348 case 'S': /* Sep */
2349 return 9;
2350 case 'O': /* Oct */
2351 return 10;
2352 case 'N': /* Nov */
2353 return 11;
2354 case 'D': /* Dec */
2355 return 12;
2356 default:
2357 return -1;
2358 }
2359 break;
2360 case MONTH_J:
2361 switch((char) toupper((unsigned char) message[index])) {
2362 case 'A':
2363 return 1;
2364 case 'U':
2365 state = MONTH_JU;
2366 break;
2367 default:
2368 return -1;
2369 }
2370 break;
2371 case MONTH_JU:
2372 switch((char) toupper((unsigned char) message[index])) {
2373 case 'N':
2374 return 6;
2375 case 'L':
2376 return 7;
2377 default:
2378 return -1;
2379 }
2380 break;
2381 case MONTH_M:
2382 switch((char) toupper((unsigned char) message[index])) {
2383 case 'A':
2384 state = MONTH_MA;
2385 break;
2386 default:
2387 return -1;
2388 }
2389 break;
2390 case MONTH_MA:
2391 switch((char) toupper((unsigned char) message[index])) {
2392 case 'Y':
2393 return 5;
2394 case 'R':
2395 return 3;
2396 default:
2397 return -1;
2398 }
2399 break;
2400 case MONTH_A:
2401 switch((char) toupper((unsigned char) message[index])) {
2402 case 'P':
2403 return 4;
2404 case 'U':
2405 return 8;
2406 default:
2407 return -1;
2408 }
2409 break;
2410 }
2411
2412 index ++;
2413 }
2414}
2415
2416static int mailimf_month_name_parse(const char * message, size_t length,
2417 size_t * index, int * result)
2418{
2419 size_t cur_token;
2420 int month;
2421 int guessed_month;
2422 int r;
2423
2424 cur_token = * index;
2425
2426 guessed_month = guess_month(message, length, cur_token);
2427 if (guessed_month == -1)
2428 return MAILIMF_ERROR_PARSE;
2429
2430 r = mailimf_token_case_insensitive_parse(message, length,
2431 &cur_token,
2432 month_names[guessed_month - 1].str);
2433 if (r != MAILIMF_NO_ERROR)
2434 return r;
2435
2436 month = guessed_month;
2437
2438 * result = month;
2439 * index = cur_token;
2440
2441 return MAILIMF_NO_ERROR;
2442}
2443
2444/*
2445day = ([FWS] 1*2DIGIT) / obs-day
2446*/
2447
2448static int mailimf_day_parse(const char * message, size_t length,
2449 size_t * index, int * result)
2450{
2451 size_t cur_token;
2452 uint32_t day;
2453 int r;
2454
2455 cur_token = * index;
2456
2457 r = mailimf_cfws_parse(message, length, &cur_token);
2458 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2459 return r;
2460
2461 r = mailimf_number_parse(message, length, &cur_token, &day);
2462 if (r != MAILIMF_NO_ERROR)
2463 return r;
2464
2465 * result = day;
2466 * index = cur_token;
2467
2468 return MAILIMF_NO_ERROR;
2469}
2470
2471/*
2472time = time-of-day FWS zone
2473*/
2474
2475static int mailimf_time_parse(const char * message, size_t length,
2476 size_t * index,
2477 int * phour, int * pmin,
2478 int * psec,
2479 int * pzone)
2480{
2481 size_t cur_token;
2482 int hour;
2483 int min;
2484 int sec;
2485 int zone;
2486 int r;
2487
2488 cur_token = * index;
2489
2490 r = mailimf_cfws_parse(message, length, &cur_token);
2491 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2492 return r;
2493
2494 r = mailimf_time_of_day_parse(message, length, &cur_token,
2495 &hour, &min, &sec);
2496 if (r != MAILIMF_NO_ERROR)
2497 return r;
2498
2499 r = mailimf_fws_parse(message, length, &cur_token);
2500 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2501 return r;
2502
2503 r = mailimf_zone_parse(message, length, &cur_token, &zone);
2504 if (r == MAILIMF_NO_ERROR) {
2505 /* do nothing */
2506 }
2507 else if (r == MAILIMF_ERROR_PARSE) {
2508 zone = 0;
2509 }
2510 else {
2511 return r;
2512 }
2513
2514 * phour = hour;
2515 * pmin = min;
2516 * psec = sec;
2517 * pzone = zone;
2518
2519 * index = cur_token;
2520
2521 return MAILIMF_NO_ERROR;
2522}
2523
2524/*
2525time-of-day = hour ":" minute [ ":" second ]
2526*/
2527
2528static int mailimf_time_of_day_parse(const char * message, size_t length,
2529 size_t * index,
2530 int * phour, int * pmin,
2531 int * psec)
2532{
2533 int hour;
2534 int min;
2535 int sec;
2536 size_t cur_token;
2537 int r;
2538
2539 cur_token = * index;
2540
2541 r = mailimf_hour_parse(message, length, &cur_token, &hour);
2542 if (r != MAILIMF_NO_ERROR)
2543 return r;
2544
2545 r = mailimf_colon_parse(message, length, &cur_token);
2546 if (r != MAILIMF_NO_ERROR)
2547 return r;
2548
2549 r = mailimf_minute_parse(message, length, &cur_token, &min);
2550 if (r != MAILIMF_NO_ERROR)
2551 return r;
2552
2553 r = mailimf_colon_parse(message, length, &cur_token);
2554 if (r == MAILIMF_NO_ERROR) {
2555 r = mailimf_second_parse(message, length, &cur_token, &sec);
2556 if (r != MAILIMF_NO_ERROR)
2557 return r;
2558 }
2559 else if (r == MAILIMF_ERROR_PARSE)
2560 sec = 0;
2561 else
2562 return r;
2563
2564 * phour = hour;
2565 * pmin = min;
2566 * psec = sec;
2567 * index = cur_token;
2568
2569 return MAILIMF_NO_ERROR;
2570}
2571
2572/*
2573hour = 2DIGIT / obs-hour
2574*/
2575
2576static int mailimf_hour_parse(const char * message, size_t length,
2577 size_t * index, int * result)
2578{
2579 uint32_t hour;
2580 int r;
2581
2582 r = mailimf_number_parse(message, length, index, &hour);
2583 if (r != MAILIMF_NO_ERROR)
2584 return r;
2585
2586 * result = hour;
2587
2588 return MAILIMF_NO_ERROR;
2589}
2590
2591/*
2592minute = 2DIGIT / obs-minute
2593*/
2594
2595static int mailimf_minute_parse(const char * message, size_t length,
2596 size_t * index, int * result)
2597{
2598 uint32_t minute;
2599 int r;
2600
2601 r = mailimf_number_parse(message, length, index, &minute);
2602 if (r != MAILIMF_NO_ERROR)
2603 return r;
2604
2605 * result = minute;
2606
2607 return MAILIMF_NO_ERROR;
2608}
2609
2610/*
2611second = 2DIGIT / obs-second
2612*/
2613
2614static int mailimf_second_parse(const char * message, size_t length,
2615 size_t * index, int * result)
2616{
2617 uint32_t second;
2618 int r;
2619
2620 r = mailimf_number_parse(message, length, index, &second);
2621 if (r != MAILIMF_NO_ERROR)
2622 return r;
2623
2624 * result = second;
2625
2626 return MAILIMF_NO_ERROR;
2627}
2628
2629/*
2630zone = (( "+" / "-" ) 4DIGIT) / obs-zone
2631*/
2632
2633/*
2634obs-zone = "UT" / "GMT" / ; Universal Time
2635 ; North American UT
2636 ; offsets
2637 "EST" / "EDT" / ; Eastern: - 5/ - 4
2638 "CST" / "CDT" / ; Central: - 6/ - 5
2639 "MST" / "MDT" / ; Mountain: - 7/ - 6
2640 "PST" / "PDT" / ; Pacific: - 8/ - 7
2641
2642 %d65-73 / ; Military zones - "A"
2643 %d75-90 / ; through "I" and "K"
2644 %d97-105 / ; through "Z", both
2645 %d107-122 ; upper and lower case
2646*/
2647
2648enum {
2649 STATE_ZONE_1 = 0,
2650 STATE_ZONE_2 = 1,
2651 STATE_ZONE_3 = 2,
2652 STATE_ZONE_OK = 3,
2653 STATE_ZONE_ERR = 4,
2654 STATE_ZONE_CONT = 5,
2655};
2656
2657static int mailimf_zone_parse(const char * message, size_t length,
2658 size_t * index, int * result)
2659{
2660 uint32_t zone;
2661 int sign;
2662 size_t cur_token;
2663 int r;
2664
2665 cur_token = * index;
2666
2667 if (cur_token + 1 < length) {
2668 if ((message[cur_token] == 'U') && (message[cur_token] == 'T')) {
2669 * result = TRUE;
2670 * index = cur_token + 2;
2671
2672 return MAILIMF_NO_ERROR;
2673 }
2674 }
2675
2676 if (cur_token + 2 < length) {
2677 int state;
2678
2679 state = STATE_ZONE_1;
2680
2681 while (state <= 2) {
2682 switch (state) {
2683 case STATE_ZONE_1:
2684 switch (message[cur_token]) {
2685 case 'G':
2686 if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') {
2687 zone = 0;
2688 state = STATE_ZONE_OK;
2689 }
2690 else {
2691 state = STATE_ZONE_ERR;
2692 }
2693 break;
2694 case 'E':
2695 zone = -5;
2696 state = STATE_ZONE_2;
2697 break;
2698 case 'C':
2699 zone = -6;
2700 state = STATE_ZONE_2;
2701 break;
2702 case 'M':
2703 zone = -7;
2704 state = STATE_ZONE_2;
2705 break;
2706 case 'P':
2707 zone = -8;
2708 state = STATE_ZONE_2;
2709 break;
2710 default:
2711 state = STATE_ZONE_CONT;
2712 break;
2713 }
2714 break;
2715 case STATE_ZONE_2:
2716 switch (message[cur_token + 1]) {
2717 case 'S':
2718 state = STATE_ZONE_3;
2719 break;
2720 case 'D':
2721 zone ++;
2722 state = STATE_ZONE_3;
2723 break;
2724 default:
2725 state = STATE_ZONE_ERR;
2726 break;
2727 }
2728 break;
2729 case STATE_ZONE_3:
2730 if (message[cur_token + 2] == 'T') {
2731 zone *= 100;
2732 state = STATE_ZONE_OK;
2733 }
2734 else
2735 state = STATE_ZONE_ERR;
2736 break;
2737 }
2738 }
2739
2740 switch (state) {
2741 case STATE_ZONE_OK:
2742 * result = zone;
2743 * index = cur_token + 3;
2744 return MAILIMF_NO_ERROR;
2745
2746 case STATE_ZONE_ERR:
2747 return MAILIMF_ERROR_PARSE;
2748 }
2749 }
2750
2751 sign = 1;
2752 r = mailimf_plus_parse(message, length, &cur_token);
2753 if (r == MAILIMF_NO_ERROR)
2754 sign = 1;
2755
2756 if (r == MAILIMF_ERROR_PARSE) {
2757 r = mailimf_minus_parse(message, length, &cur_token);
2758 if (r == MAILIMF_NO_ERROR)
2759 sign = -1;
2760 }
2761
2762 if (r == MAILIMF_NO_ERROR) {
2763 /* do nothing */
2764 }
2765 else if (r == MAILIMF_ERROR_PARSE)
2766 sign = 1;
2767 else
2768 return r;
2769
2770 r = mailimf_number_parse(message, length, &cur_token, &zone);
2771 if (r != MAILIMF_NO_ERROR)
2772 return r;
2773
2774 zone = zone * sign;
2775
2776 * index = cur_token;
2777 * result = zone;
2778
2779 return MAILIMF_NO_ERROR;
2780}
2781
2782/*
2783address = mailbox / group
2784*/
2785
2786int mailimf_address_parse(const char * message, size_t length,
2787 size_t * index,
2788 struct mailimf_address ** result)
2789{
2790 int type;
2791 size_t cur_token;
2792 struct mailimf_mailbox * mailbox;
2793 struct mailimf_group * group;
2794 struct mailimf_address * address;
2795 int r;
2796 int res;
2797
2798 cur_token = * index;
2799
2800 mailbox = NULL;
2801 group = NULL;
2802
2803 type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */
2804 r = mailimf_group_parse(message, length, &cur_token, &group);
2805 if (r == MAILIMF_NO_ERROR)
2806 type = MAILIMF_ADDRESS_GROUP;
2807
2808 if (r == MAILIMF_ERROR_PARSE) {
2809 r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox);
2810 if (r == MAILIMF_NO_ERROR)
2811 type = MAILIMF_ADDRESS_MAILBOX;
2812 }
2813
2814 if (r != MAILIMF_NO_ERROR) {
2815 res = r;
2816 goto err;
2817 }
2818
2819 address = mailimf_address_new(type, mailbox, group);
2820 if (address == NULL) {
2821 res = MAILIMF_ERROR_MEMORY;
2822 goto free;
2823 }
2824
2825 * result = address;
2826 * index = cur_token;
2827
2828 return MAILIMF_NO_ERROR;
2829
2830 free:
2831 if (mailbox != NULL)
2832 mailimf_mailbox_free(mailbox);
2833 if (group != NULL)
2834 mailimf_group_free(group);
2835 err:
2836 return res;
2837}
2838
2839
2840/*
2841mailbox = name-addr / addr-spec
2842*/
2843
2844
2845int mailimf_mailbox_parse(const char * message, size_t length,
2846 size_t * index,
2847 struct mailimf_mailbox ** result)
2848{
2849 size_t cur_token;
2850 char * display_name;
2851 struct mailimf_mailbox * mailbox;
2852 char * addr_spec;
2853 int r;
2854 int res;
2855
2856 cur_token = * index;
2857 display_name = NULL;
2858 addr_spec = NULL;
2859
2860 r = mailimf_name_addr_parse(message, length, &cur_token,
2861 &display_name, &addr_spec);
2862 if (r == MAILIMF_ERROR_PARSE)
2863 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2864
2865 if (r != MAILIMF_NO_ERROR) {
2866 res = r;
2867 goto err;
2868 }
2869
2870 mailbox = mailimf_mailbox_new(display_name, addr_spec);
2871 if (mailbox == NULL) {
2872 res = MAILIMF_ERROR_MEMORY;
2873 goto free;
2874 }
2875
2876 * result = mailbox;
2877 * index = cur_token;
2878
2879 return MAILIMF_NO_ERROR;
2880
2881 free:
2882 if (display_name != NULL)
2883 mailimf_display_name_free(display_name);
2884 if (addr_spec != NULL)
2885 mailimf_addr_spec_free(addr_spec);
2886 err:
2887 return res;
2888}
2889
2890/*
2891name-addr = [display-name] angle-addr
2892*/
2893
2894static int mailimf_name_addr_parse(const char * message, size_t length,
2895 size_t * index,
2896 char ** pdisplay_name,
2897 char ** pangle_addr)
2898{
2899 char * display_name;
2900 char * angle_addr;
2901 size_t cur_token;
2902 int r;
2903 int res;
2904
2905 cur_token = * index;
2906
2907 display_name = NULL;
2908 angle_addr = NULL;
2909
2910 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2911 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
2912 res = r;
2913 goto err;
2914 }
2915
2916 r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr);
2917 if (r != MAILIMF_NO_ERROR) {
2918 res = r;
2919 goto free_display_name;
2920 }
2921
2922 * pdisplay_name = display_name;
2923 * pangle_addr = angle_addr;
2924 * index = cur_token;
2925
2926 return MAILIMF_NO_ERROR;
2927
2928 free_display_name:
2929 if (display_name != NULL)
2930 mailimf_display_name_free(display_name);
2931 err:
2932 return res;
2933}
2934
2935/*
2936angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
2937*/
2938
2939static int mailimf_angle_addr_parse(const char * message, size_t length,
2940 size_t * index, char ** result)
2941{
2942 size_t cur_token;
2943 char * addr_spec;
2944 int r;
2945
2946 cur_token = * index;
2947
2948 r = mailimf_cfws_parse(message, length, &cur_token);
2949 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
2950 return r;
2951
2952 r = mailimf_lower_parse(message, length, &cur_token);
2953 if (r != MAILIMF_NO_ERROR)
2954 return r;
2955
2956 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
2957 if (r != MAILIMF_NO_ERROR)
2958 return r;
2959
2960 r = mailimf_greater_parse(message, length, &cur_token);
2961 if (r != MAILIMF_NO_ERROR) {
2962 free(addr_spec);
2963 return r;
2964 }
2965
2966 * result = addr_spec;
2967 * index = cur_token;
2968
2969 return MAILIMF_NO_ERROR;
2970}
2971
2972/*
2973group = display-name ":" [mailbox-list / CFWS] ";"
2974 [CFWS]
2975*/
2976
2977static int mailimf_group_parse(const char * message, size_t length,
2978 size_t * index,
2979 struct mailimf_group ** result)
2980{
2981 size_t cur_token;
2982 char * display_name;
2983 struct mailimf_mailbox_list * mailbox_list;
2984 struct mailimf_group * group;
2985 int r;
2986 int res;
2987
2988 cur_token = * index;
2989
2990 mailbox_list = NULL;
2991
2992 r = mailimf_display_name_parse(message, length, &cur_token, &display_name);
2993 if (r != MAILIMF_NO_ERROR) {
2994 res = r;
2995 goto err;
2996 }
2997
2998 r = mailimf_colon_parse(message, length, &cur_token);
2999 if (r != MAILIMF_NO_ERROR) {
3000 res = r;
3001 goto free_display_name;
3002 }
3003
3004 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list);
3005 switch (r) {
3006 case MAILIMF_NO_ERROR:
3007 break;
3008 case MAILIMF_ERROR_PARSE:
3009 r = mailimf_cfws_parse(message, length, &cur_token);
3010 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3011 return r;
3012 break;
3013 default:
3014 return r;
3015 }
3016
3017 r = mailimf_semi_colon_parse(message, length, &cur_token);
3018 if (r != MAILIMF_NO_ERROR) {
3019 res = r;
3020 goto free_mailbox_list;
3021 }
3022
3023 group = mailimf_group_new(display_name, mailbox_list);
3024 if (group == NULL) {
3025 res = MAILIMF_ERROR_MEMORY;
3026 goto free_mailbox_list;
3027 }
3028
3029 * index = cur_token;
3030 * result = group;
3031
3032 return MAILIMF_NO_ERROR;
3033
3034 free_mailbox_list:
3035 mailimf_mailbox_list_free(mailbox_list);
3036 free_display_name:
3037 mailimf_display_name_free(display_name);
3038 err:
3039 return res;
3040}
3041
3042/*
3043display-name = phrase
3044*/
3045
3046static int mailimf_display_name_parse(const char * message, size_t length,
3047 size_t * index, char ** result)
3048{
3049 return mailimf_phrase_parse(message, length, index, result);
3050}
3051
3052/*
3053mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
3054*/
3055
3056int
3057mailimf_mailbox_list_parse(const char * message, size_t length,
3058 size_t * index,
3059 struct mailimf_mailbox_list ** result)
3060{
3061 size_t cur_token;
3062 clist * list;
3063 struct mailimf_mailbox_list * mailbox_list;
3064 int r;
3065 int res;
3066
3067 cur_token = * index;
3068
3069 r = mailimf_struct_list_parse(message, length,
3070 &cur_token, &list, ',',
3071 (mailimf_struct_parser *)
3072 mailimf_mailbox_parse,
3073 (mailimf_struct_destructor *)
3074 mailimf_mailbox_free);
3075 if (r != MAILIMF_NO_ERROR) {
3076 res = r;
3077 goto err;
3078 }
3079
3080 mailbox_list = mailimf_mailbox_list_new(list);
3081 if (mailbox_list == NULL) {
3082 res = MAILIMF_ERROR_MEMORY;
3083 goto free_list;
3084 }
3085
3086 * result = mailbox_list;
3087 * index = cur_token;
3088
3089 return MAILIMF_NO_ERROR;
3090
3091 free_list:
3092 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
3093 clist_free(list);
3094 err:
3095 return res;
3096 }
3097
3098/*
3099address-list = (address *("," address)) / obs-addr-list
3100*/
3101
3102
3103int
3104mailimf_address_list_parse(const char * message, size_t length,
3105 size_t * index,
3106 struct mailimf_address_list ** result)
3107{
3108 size_t cur_token;
3109 clist * list;
3110 struct mailimf_address_list * address_list;
3111 int r;
3112 int res;
3113
3114 cur_token = * index;
3115
3116 r = mailimf_struct_list_parse(message, length,
3117 &cur_token, &list, ',',
3118 (mailimf_struct_parser *)
3119 mailimf_address_parse,
3120 (mailimf_struct_destructor *)
3121 mailimf_address_free);
3122 if (r != MAILIMF_NO_ERROR) {
3123 res = r;
3124 goto err;
3125 }
3126
3127 address_list = mailimf_address_list_new(list);
3128 if (address_list == NULL) {
3129 res = MAILIMF_ERROR_MEMORY;
3130 goto free_list;
3131 }
3132
3133 * result = address_list;
3134 * index = cur_token;
3135
3136 return MAILIMF_NO_ERROR;
3137
3138 free_list:
3139 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
3140 clist_free(list);
3141 err:
3142 return res;
3143 }
3144
3145/*
3146addr-spec = local-part "@" domain
3147*/
3148
3149
3150static int mailimf_addr_spec_parse(const char * message, size_t length,
3151 size_t * index,
3152 char ** result)
3153{
3154 size_t cur_token;
3155#if 0
3156 char * local_part;
3157 char * domain;
3158#endif
3159 char * addr_spec;
3160 int r;
3161 int res;
3162 size_t begin;
3163 size_t end;
3164 int final;
3165 size_t count;
3166 const char * src;
3167 char * dest;
3168 size_t i;
3169
3170 cur_token = * index;
3171
3172 r = mailimf_cfws_parse(message, length, &cur_token);
3173 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3174 res = r;
3175 goto err;
3176 }
3177
3178 end = cur_token;
3179 if (end >= length) {
3180 res = MAILIMF_ERROR_PARSE;
3181 goto err;
3182 }
3183
3184 begin = cur_token;
3185
3186 final = FALSE;
3187 while (1) {
3188 switch (message[end]) {
3189 case '>':
3190 case ',':
3191 case '\r':
3192 case '\n':
3193 case '(':
3194 case ')':
3195 case ':':
3196 case ';':
3197 final = TRUE;
3198 break;
3199 }
3200
3201 if (final)
3202 break;
3203
3204 end ++;
3205 if (end >= length)
3206 break;
3207 }
3208
3209 if (end == begin) {
3210 res = MAILIMF_ERROR_PARSE;
3211 goto err;
3212 }
3213
3214 addr_spec = malloc(end - cur_token + 1);
3215 if (addr_spec == NULL) {
3216 res = MAILIMF_ERROR_MEMORY;
3217 goto err;
3218 }
3219
3220 count = end - cur_token;
3221 src = message + cur_token;
3222 dest = addr_spec;
3223 for(i = 0 ; i < count ; i ++) {
3224 if ((* src != ' ') && (* src != '\t')) {
3225 * dest = * src;
3226 dest ++;
3227 }
3228 src ++;
3229 }
3230 * dest = '\0';
3231
3232#if 0
3233 strncpy(addr_spec, message + cur_token, end - cur_token);
3234 addr_spec[end - cur_token] = '\0';
3235#endif
3236
3237 cur_token = end;
3238
3239#if 0
3240 r = mailimf_local_part_parse(message, length, &cur_token, &local_part);
3241 if (r != MAILIMF_NO_ERROR) {
3242 res = r;
3243 goto err;
3244 }
3245
3246 r = mailimf_at_sign_parse(message, length, &cur_token);
3247 switch (r) {
3248 case MAILIMF_NO_ERROR:
3249 r = mailimf_domain_parse(message, length, &cur_token, &domain);
3250 if (r != MAILIMF_NO_ERROR) {
3251 res = r;
3252 goto free_local_part;
3253 }
3254 break;
3255
3256 case MAILIMF_ERROR_PARSE:
3257 domain = NULL;
3258 break;
3259
3260 default:
3261 res = r;
3262 goto free_local_part;
3263 }
3264
3265 if (domain) {
3266 addr_spec = malloc(strlen(local_part) + strlen(domain) + 2);
3267 if (addr_spec == NULL) {
3268 res = MAILIMF_ERROR_MEMORY;
3269 goto free_domain;
3270 }
3271
3272 strcpy(addr_spec, local_part);
3273 strcat(addr_spec, "@");
3274 strcat(addr_spec, domain);
3275
3276 mailimf_domain_free(domain);
3277 mailimf_local_part_free(local_part);
3278 }
3279 else {
3280 addr_spec = local_part;
3281 }
3282#endif
3283
3284 * result = addr_spec;
3285 * index = cur_token;
3286
3287 return MAILIMF_NO_ERROR;
3288
3289#if 0
3290 free_domain:
3291 mailimf_domain_free(domain);
3292 free_local_part:
3293 mailimf_local_part_free(local_part);
3294#endif
3295 err:
3296 return res;
3297}
3298
3299/*
3300local-part = dot-atom / quoted-string / obs-local-part
3301*/
3302
3303#if 0
3304static int mailimf_local_part_parse(const char * message, size_t length,
3305 size_t * index,
3306 char ** result)
3307{
3308 int r;
3309
3310 r = mailimf_dot_atom_parse(message, length, index, result);
3311 switch (r) {
3312 case MAILIMF_NO_ERROR:
3313 return r;
3314 case MAILIMF_ERROR_PARSE:
3315 break;
3316 default:
3317 return r;
3318 }
3319
3320 r = mailimf_quoted_string_parse(message, length, index, result);
3321 if (r != MAILIMF_NO_ERROR)
3322 return r;
3323
3324 return MAILIMF_NO_ERROR;
3325}
3326#endif
3327
3328/*
3329domain = dot-atom / domain-literal / obs-domain
3330*/
3331
3332#if 0
3333static int mailimf_domain_parse(const char * message, size_t length,
3334 size_t * index,
3335 char ** result)
3336{
3337 int r;
3338
3339 r = mailimf_dot_atom_parse(message, length, index, result);
3340 switch (r) {
3341 case MAILIMF_NO_ERROR:
3342 return r;
3343 case MAILIMF_ERROR_PARSE:
3344 break;
3345 default:
3346 return r;
3347 }
3348
3349 r = mailimf_domain_literal_parse(message, length, index, result);
3350 if (r != MAILIMF_NO_ERROR)
3351 return r;
3352
3353 return MAILIMF_NO_ERROR;
3354}
3355#endif
3356
3357/*
3358[FWS] dcontent
3359*/
3360
3361#if 0
3362static int
3363mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length,
3364 size_t * index)
3365{
3366 size_t cur_token;
3367 char ch;
3368 int r;
3369
3370 cur_token = * index;
3371
3372 r = mailimf_cfws_parse(message, length, &cur_token);
3373 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3374 return r;
3375
3376 r = mailimf_dcontent_parse(message, length, &cur_token, &ch);
3377 if (r != MAILIMF_NO_ERROR)
3378 return r;
3379
3380 * index = cur_token;
3381
3382 return MAILIMF_NO_ERROR;
3383}
3384#endif
3385
3386/*
3387domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
3388*/
3389
3390#if 0
3391static int mailimf_domain_literal_parse(const char * message, size_t length,
3392 size_t * index, char ** result)
3393{
3394 size_t cur_token;
3395 int len;
3396 int begin;
3397 char * domain_literal;
3398 int r;
3399
3400 cur_token = * index;
3401
3402 r = mailimf_cfws_parse(message, length, &cur_token);
3403 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3404 return r;
3405
3406 begin = cur_token;
3407 r = mailimf_obracket_parse(message, length, &cur_token);
3408 if (r != MAILIMF_NO_ERROR)
3409 return r;
3410
3411 while (1) {
3412 r = mailimf_domain_literal_fws_dcontent_parse(message, length,
3413 &cur_token);
3414 if (r == MAILIMF_NO_ERROR) {
3415 /* do nothing */
3416 }
3417 else if (r == MAILIMF_ERROR_PARSE)
3418 break;
3419 else
3420 return r;
3421 }
3422
3423 r = mailimf_fws_parse(message, length, &cur_token);
3424 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
3425 return r;
3426
3427 r = mailimf_cbracket_parse(message, length, &cur_token);
3428 if (r != MAILIMF_NO_ERROR)
3429 return r;
3430
3431 len = cur_token - begin;
3432
3433 domain_literal = malloc(len + 1);
3434 if (domain_literal == NULL)
3435 return MAILIMF_ERROR_MEMORY;
3436 strncpy(domain_literal, message + begin, len);
3437 domain_literal[len] = '\0';
3438
3439 * result = domain_literal;
3440 * index = cur_token;
3441
3442 return MAILIMF_NO_ERROR;
3443}
3444#endif
3445
3446/*
3447dcontent = dtext / quoted-pair
3448*/
3449
3450#if 0
3451static int mailimf_dcontent_parse(const char * message, size_t length,
3452 size_t * index, char * result)
3453{
3454 size_t cur_token;
3455 char ch;
3456 int r;
3457
3458 cur_token = * index;
3459
3460 if (cur_token >= length)
3461 return MAILIMF_ERROR_PARSE;
3462
3463 if (is_dtext(message[cur_token])) {
3464 ch = message[cur_token];
3465 cur_token ++;
3466 }
3467 else {
3468 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
3469
3470 if (r != MAILIMF_NO_ERROR)
3471 return r;
3472 }
3473
3474 * index = cur_token;
3475 * result = ch;
3476
3477 return MAILIMF_NO_ERROR;
3478}
3479#endif
3480
3481
3482/*
3483dtext = NO-WS-CTL / ; Non white space controls
3484
3485 %d33-90 / ; The rest of the US-ASCII
3486 %d94-126 ; characters not including "[",
3487 ; "]", or "\"
3488*/
3489
3490static inline int is_dtext(char ch)
3491{
3492 unsigned char uch = (unsigned char) ch;
3493
3494 if (is_no_ws_ctl(ch))
3495 return TRUE;
3496
3497 if (uch < 33)
3498 return FALSE;
3499
3500 if ((uch >= 91) && (uch <= 93))
3501 return FALSE;
3502
3503 if (uch == 127)
3504 return FALSE;
3505
3506 return TRUE;
3507}
3508
3509/*
3510message = (fields / obs-fields)
3511 [CRLF body]
3512*/
3513
3514int mailimf_message_parse(const char * message, size_t length,
3515 size_t * index,
3516 struct mailimf_message ** result)
3517{
3518 struct mailimf_fields * fields;
3519 struct mailimf_body * body;
3520 struct mailimf_message * msg;
3521 size_t cur_token;
3522 int r;
3523 int res;
3524
3525 cur_token = * index;
3526
3527 r = mailimf_fields_parse(message, length, &cur_token, &fields);
3528 if (r != MAILIMF_NO_ERROR) {
3529 res = r;
3530 goto err;
3531 }
3532
3533 r = mailimf_crlf_parse(message, length, &cur_token);
3534 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3535 res = r;
3536 goto err;
3537 }
3538
3539 r = mailimf_body_parse(message, length, &cur_token, &body);
3540 if (r != MAILIMF_NO_ERROR) {
3541 res = r;
3542 goto free_fields;
3543 }
3544
3545 msg = mailimf_message_new(fields, body);
3546 if (msg == NULL) {
3547 res = MAILIMF_ERROR_MEMORY;
3548 goto free_body;
3549 }
3550
3551 * index = cur_token;
3552 * result = msg;
3553
3554 return MAILIMF_NO_ERROR;
3555
3556 free_body:
3557 mailimf_body_free(body);
3558 free_fields:
3559 mailimf_fields_free(fields);
3560 err:
3561 return res;
3562}
3563
3564/*
3565body = *(*998text CRLF) *998text
3566*/
3567
3568int mailimf_body_parse(const char * message, size_t length,
3569 size_t * index,
3570 struct mailimf_body ** result)
3571{
3572 size_t cur_token;
3573 struct mailimf_body * body;
3574
3575 cur_token = * index;
3576
3577 body = mailimf_body_new(message + cur_token, length - cur_token);
3578 if (body == NULL)
3579 return MAILIMF_ERROR_MEMORY;
3580
3581 cur_token = length;
3582
3583 * result = body;
3584 * index = cur_token;
3585
3586 return MAILIMF_NO_ERROR;
3587}
3588
3589/*
3590CHANGE TO THE RFC 2822
3591
3592original :
3593
3594fields = *(trace
3595 *(resent-date /
3596 resent-from /
3597 resent-sender /
3598 resent-to /
3599 resent-cc /
3600 resent-bcc /
3601 resent-msg-id))
3602 *(orig-date /
3603 from /
3604 sender /
3605 reply-to /
3606 to /
3607 cc /
3608 bcc /
3609 message-id /
3610 in-reply-to /
3611 references /
3612 subject /
3613 comments /
3614 keywords /
3615 optional-field)
3616
3617INTO THE FOLLOWING :
3618*/
3619
3620/*
3621resent-fields-list = *(resent-date /
3622 resent-from /
3623 resent-sender /
3624 resent-to /
3625 resent-cc /
3626 resent-bcc /
3627 resent-msg-id))
3628*/
3629
3630#if 0
3631enum {
3632 RESENT_HEADER_START,
3633};
3634
3635static int guess_resent_header_type(char * message,
3636 size_t length, size_t index)
3637{
3638 int r;
3639
3640 r = mailimf_token_case_insensitive_parse(message,
3641 length, &index, "Resent-");
3642 if (r != MAILIMF_NO_ERROR)
3643 return MAILIMF_RESENT_FIELD_NONE;
3644
3645 if (index >= length)
3646 return MAILIMF_RESENT_FIELD_NONE;
3647
3648 switch(toupper(message[index])) {
3649 case 'D':
3650 return MAILIMF_RESENT_FIELD_DATE;
3651 case 'F':
3652 return MAILIMF_RESENT_FIELD_FROM;
3653 case 'S':
3654 return MAILIMF_RESENT_FIELD_SENDER;
3655 case 'T':
3656 return MAILIMF_RESENT_FIELD_TO;
3657 case 'C':
3658 return MAILIMF_RESENT_FIELD_CC;
3659 case 'B':
3660 return MAILIMF_RESENT_FIELD_BCC;
3661 case 'M':
3662 return MAILIMF_RESENT_FIELD_MSG_ID;
3663 default:
3664 return MAILIMF_RESENT_FIELD_NONE;
3665 }
3666}
3667#endif
3668
3669#if 0
3670static int
3671mailimf_resent_field_parse(const char * message, size_t length,
3672 size_t * index,
3673 struct mailimf_resent_field ** result)
3674{
3675 struct mailimf_orig_date * resent_date;
3676 struct mailimf_from * resent_from;
3677 struct mailimf_sender * resent_sender;
3678 struct mailimf_to* resent_to;
3679 struct mailimf_cc * resent_cc;
3680 struct mailimf_bcc * resent_bcc;
3681 struct mailimf_message_id * resent_msg_id;
3682 size_t cur_token;
3683 int type;
3684 struct mailimf_resent_field * resent_field;
3685 int r;
3686 int res;
3687
3688 cur_token = * index;
3689
3690 resent_date = NULL;
3691 resent_from = NULL;
3692 resent_sender = NULL;
3693 resent_to = NULL;
3694 resent_cc = NULL;
3695 resent_bcc = NULL;
3696 resent_msg_id = NULL;
3697
3698 type = guess_resent_header_type(message, length, cur_token);
3699
3700 switch(type) {
3701 case MAILIMF_RESENT_FIELD_DATE:
3702 r = mailimf_resent_date_parse(message, length, &cur_token,
3703 &resent_date);
3704 if (r != MAILIMF_NO_ERROR) {
3705 res = r;
3706 goto err;
3707 }
3708 break;
3709 case MAILIMF_RESENT_FIELD_FROM:
3710 r = mailimf_resent_from_parse(message, length, &cur_token,
3711 &resent_from);
3712 if (r != MAILIMF_NO_ERROR) {
3713 res = r;
3714 goto err;
3715 }
3716 break;
3717 case MAILIMF_RESENT_FIELD_SENDER:
3718 r = mailimf_resent_sender_parse(message, length, &cur_token,
3719 &resent_sender);
3720 if (r != MAILIMF_NO_ERROR) {
3721 res = r;
3722 goto err;
3723 }
3724 break;
3725 case MAILIMF_RESENT_FIELD_TO:
3726 r = mailimf_resent_to_parse(message, length, &cur_token,
3727 &resent_to);
3728 if (r != MAILIMF_NO_ERROR) {
3729 res = r;
3730 goto err;
3731 }
3732 break;
3733 case MAILIMF_RESENT_FIELD_CC:
3734 r= mailimf_resent_cc_parse(message, length, &cur_token,
3735 &resent_cc);
3736 if (r != MAILIMF_NO_ERROR) {
3737 res = r;
3738 goto err;
3739 }
3740 break;
3741 case MAILIMF_RESENT_FIELD_BCC:
3742 r = mailimf_resent_bcc_parse(message, length, &cur_token,
3743 &resent_bcc);
3744 if (r != MAILIMF_NO_ERROR) {
3745 res = r;
3746 goto err;
3747 }
3748 break;
3749 case MAILIMF_RESENT_FIELD_MSG_ID:
3750 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
3751 &resent_msg_id);
3752 if (r != MAILIMF_NO_ERROR) {
3753 res = r;
3754 goto err;
3755 }
3756 break;
3757 default:
3758 res = MAILIMF_ERROR_PARSE;
3759 goto err;
3760 }
3761
3762 resent_field = mailimf_resent_field_new(type, resent_date,
3763 resent_from, resent_sender,
3764 resent_to, resent_cc,
3765 resent_bcc, resent_msg_id);
3766 if (resent_field == NULL) {
3767 res = MAILIMF_ERROR_MEMORY;
3768 goto free_resent;
3769 }
3770
3771 * result = resent_field;
3772 * index = cur_token;
3773
3774 return MAILIMF_NO_ERROR;
3775
3776 free_resent:
3777 if (resent_msg_id != NULL)
3778 mailimf_message_id_free(resent_msg_id);
3779 if (resent_bcc != NULL)
3780 mailimf_bcc_free(resent_bcc);
3781 if (resent_cc != NULL)
3782 mailimf_cc_free(resent_cc);
3783 if (resent_to != NULL)
3784 mailimf_to_free(resent_to);
3785 if (resent_sender != NULL)
3786 mailimf_sender_free(resent_sender);
3787 if (resent_from != NULL)
3788 mailimf_from_free(resent_from);
3789 if (resent_date != NULL)
3790 mailimf_orig_date_free(resent_date);
3791 err:
3792 return res;
3793}
3794#endif
3795
3796#if 0
3797static int
3798mailimf_resent_fields_list_parse(const char * message, size_t length,
3799 size_t * index,
3800 struct mailimf_resent_fields_list ** result)
3801{
3802 clist * list;
3803 size_t cur_token;
3804 struct mailimf_resent_fields_list * resent_fields_list;
3805 int r;
3806 int res;
3807
3808 cur_token = * index;
3809 list = NULL;
3810
3811 r = mailimf_struct_multiple_parse(message, length, &cur_token, &list,
3812 (mailimf_struct_parser *)
3813 mailimf_resent_field_parse,
3814 (mailimf_struct_destructor *)
3815 mailimf_resent_field_free);
3816 if (r != MAILIMF_NO_ERROR) {
3817 res = r;
3818 goto err;
3819 }
3820
3821 resent_fields_list = mailimf_resent_fields_list_new(list);
3822 if (resent_fields_list == NULL) {
3823 res = MAILIMF_ERROR_MEMORY;
3824 goto free_list;
3825 }
3826
3827 * result = resent_fields_list;
3828 * index = cur_token;
3829
3830 return MAILIMF_NO_ERROR;
3831
3832 free_list:
3833 clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL);
3834 clist_free(list);
3835 err:
3836 return res;
3837}
3838#endif
3839
3840/*
3841 ([trace]
3842 [resent-fields-list])
3843*/
3844
3845#if 0
3846static int
3847mailimf_trace_resent_fields_parse(const char * message, size_t length,
3848 size_t * index,
3849 struct mailimf_trace_resent_fields ** result)
3850{
3851 size_t cur_token;
3852 struct mailimf_return * return_path;
3853 struct mailimf_resent_fields_list * resent_fields;
3854 struct mailimf_trace_resent_fields * trace_resent_fields;
3855 int res;
3856 int r;
3857
3858 cur_token = * index;
3859
3860 return_path = NULL;
3861 resent_fields = NULL;
3862
3863 r = mailimf_return_parse(message, length, &cur_token,
3864 &return_path);
3865 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3866 res = r;
3867 goto err;
3868 }
3869
3870 r = mailimf_resent_fields_list_parse(message, length, &cur_token,
3871 &resent_fields);
3872 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
3873 res = r;
3874 goto err;
3875 }
3876
3877 if ((return_path == NULL) && (resent_fields == NULL)) {
3878 res = MAILIMF_ERROR_PARSE;
3879 goto err;
3880 }
3881
3882 trace_resent_fields = mailimf_trace_resent_fields_new(return_path,
3883 resent_fields);
3884 if (trace_resent_fields == NULL) {
3885 res = MAILIMF_ERROR_MEMORY;
3886 goto free_resent_fields;
3887 }
3888
3889 * result = trace_resent_fields;
3890 * index = cur_token;
3891
3892 return MAILIMF_NO_ERROR;
3893
3894 free_resent_fields:
3895 if (resent_fields != NULL)
3896 mailimf_resent_fields_list_free(resent_fields);
3897 if (return_path != NULL)
3898 mailimf_return_free(return_path);
3899 err:
3900 return res;
3901}
3902#endif
3903
3904/*
3905delivering-info = *([trace]
3906 [resent-fields-list])
3907*/
3908
3909#if 0
3910static int
3911mailimf_delivering_info_parse(const char * message, size_t length,
3912 size_t * index,
3913 struct mailimf_delivering_info ** result)
3914{
3915 size_t cur_token;
3916 clist * list;
3917 struct mailimf_delivering_info * delivering_info;
3918 int r;
3919 int res;
3920
3921 cur_token = * index;
3922
3923 r = mailimf_struct_multiple_parse(message, length, &cur_token,
3924 &list,
3925 (mailimf_struct_parser *)
3926 mailimf_trace_resent_fields_parse,
3927 (mailimf_struct_destructor *)
3928 mailimf_trace_resent_fields_free);
3929 if (r != MAILIMF_NO_ERROR) {
3930 res = r;
3931 goto err;
3932 }
3933
3934 delivering_info = mailimf_delivering_info_new(list);
3935 if (delivering_info == NULL) {
3936 res = MAILIMF_ERROR_MEMORY;
3937 goto free_list;
3938 }
3939
3940 * result = delivering_info;
3941 * index = cur_token;
3942
3943 return MAILIMF_NO_ERROR;
3944
3945 free_list:
3946 clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL);
3947 clist_free(list);
3948 err:
3949 return res;
3950}
3951#endif
3952
3953/*
3954field = delivering-info /
3955 orig-date /
3956 from /
3957 sender /
3958 reply-to /
3959 to /
3960 cc /
3961 bcc /
3962 message-id /
3963 in-reply-to /
3964 references /
3965 subject /
3966 comments /
3967 keywords /
3968 optional-field
3969*/
3970
3971enum {
3972 HEADER_START,
3973 HEADER_C,
3974 HEADER_R,
3975 HEADER_RE,
3976 HEADER_S,
3977 HEADER_RES,
3978};
3979
3980static int guess_header_type(const char * message, size_t length, size_t index)
3981{
3982 int state;
3983 int r;
3984
3985 state = HEADER_START;
3986
3987 while (1) {
3988
3989 if (index >= length)
3990 return MAILIMF_FIELD_NONE;
3991
3992 switch(state) {
3993 case HEADER_START:
3994 switch((char) toupper((unsigned char) message[index])) {
3995 case 'B':
3996 return MAILIMF_FIELD_BCC;
3997 case 'C':
3998 state = HEADER_C;
3999 break;
4000 case 'D':
4001 return MAILIMF_FIELD_ORIG_DATE;
4002 case 'F':
4003 return MAILIMF_FIELD_FROM;
4004 case 'I':
4005 return MAILIMF_FIELD_IN_REPLY_TO;
4006 case 'K':
4007 return MAILIMF_FIELD_KEYWORDS;
4008 case 'M':
4009 return MAILIMF_FIELD_MESSAGE_ID;
4010 case 'R':
4011 state = HEADER_R;
4012 break;
4013 case 'T':
4014 return MAILIMF_FIELD_TO;
4015 break;
4016 case 'S':
4017 state = HEADER_S;
4018 break;
4019 default:
4020 return MAILIMF_FIELD_NONE;
4021 }
4022 break;
4023 case HEADER_C:
4024 switch((char) toupper((unsigned char) message[index])) {
4025 case 'O':
4026 return MAILIMF_FIELD_COMMENTS;
4027 case 'C':
4028 return MAILIMF_FIELD_CC;
4029 default:
4030 return MAILIMF_FIELD_NONE;
4031 }
4032 break;
4033 case HEADER_R:
4034 switch((char) toupper((unsigned char) message[index])) {
4035 case 'E':
4036 state = HEADER_RE;
4037 break;
4038 default:
4039 return MAILIMF_FIELD_NONE;
4040 }
4041 break;
4042 case HEADER_RE:
4043 switch((char) toupper((unsigned char) message[index])) {
4044 case 'F':
4045 return MAILIMF_FIELD_REFERENCES;
4046 case 'P':
4047 return MAILIMF_FIELD_REPLY_TO;
4048 case 'S':
4049 state = HEADER_RES;
4050 break;
4051 case 'T':
4052 return MAILIMF_FIELD_RETURN_PATH;
4053 default:
4054 return MAILIMF_FIELD_NONE;
4055 }
4056 break;
4057 case HEADER_S:
4058 switch((char) toupper((unsigned char) message[index])) {
4059 case 'E':
4060 return MAILIMF_FIELD_SENDER;
4061 case 'U':
4062 return MAILIMF_FIELD_SUBJECT;
4063 default:
4064 return MAILIMF_FIELD_NONE;
4065 }
4066 break;
4067
4068 case HEADER_RES:
4069 r = mailimf_token_case_insensitive_parse(message,
4070 length, &index, "ent-");
4071 if (r != MAILIMF_NO_ERROR)
4072 return MAILIMF_FIELD_NONE;
4073
4074 if (index >= length)
4075 return MAILIMF_FIELD_NONE;
4076
4077 switch((char) toupper((unsigned char) message[index])) {
4078 case 'D':
4079 return MAILIMF_FIELD_RESENT_DATE;
4080 case 'F':
4081 return MAILIMF_FIELD_RESENT_FROM;
4082 case 'S':
4083 return MAILIMF_FIELD_RESENT_SENDER;
4084 case 'T':
4085 return MAILIMF_FIELD_RESENT_TO;
4086 case 'C':
4087 return MAILIMF_FIELD_RESENT_CC;
4088 case 'B':
4089 return MAILIMF_FIELD_RESENT_BCC;
4090 case 'M':
4091 return MAILIMF_FIELD_RESENT_MSG_ID;
4092 default:
4093 return MAILIMF_FIELD_NONE;
4094 }
4095 break;
4096 }
4097 index ++;
4098 }
4099}
4100
4101static int mailimf_field_parse(const char * message, size_t length,
4102 size_t * index,
4103 struct mailimf_field ** result)
4104{
4105 size_t cur_token;
4106 int type;
4107 struct mailimf_return * return_path;
4108 struct mailimf_orig_date * resent_date;
4109 struct mailimf_from * resent_from;
4110 struct mailimf_sender * resent_sender;
4111 struct mailimf_to* resent_to;
4112 struct mailimf_cc * resent_cc;
4113 struct mailimf_bcc * resent_bcc;
4114 struct mailimf_message_id * resent_msg_id;
4115 struct mailimf_orig_date * orig_date;
4116 struct mailimf_from * from;
4117 struct mailimf_sender * sender;
4118 struct mailimf_reply_to * reply_to;
4119 struct mailimf_to * to;
4120 struct mailimf_cc * cc;
4121 struct mailimf_bcc * bcc;
4122 struct mailimf_message_id * message_id;
4123 struct mailimf_in_reply_to * in_reply_to;
4124 struct mailimf_references * references;
4125 struct mailimf_subject * subject;
4126 struct mailimf_comments * comments;
4127 struct mailimf_keywords * keywords;
4128 struct mailimf_optional_field * optional_field;
4129 struct mailimf_field * field;
4130 int guessed_type;
4131 int r;
4132 int res;
4133
4134 cur_token = * index;
4135
4136 return_path = NULL;
4137 resent_date = NULL;
4138 resent_from = NULL;
4139 resent_sender = NULL;
4140 resent_to = NULL;
4141 resent_cc = NULL;
4142 resent_bcc = NULL;
4143 resent_msg_id = NULL;
4144 orig_date = NULL;
4145 from = NULL;
4146 sender = NULL;
4147 reply_to = NULL;
4148 to = NULL;
4149 cc = NULL;
4150 bcc = NULL;
4151 message_id = NULL;
4152 in_reply_to = NULL;
4153 references = NULL;
4154 subject = NULL;
4155 comments = NULL;
4156 keywords = NULL;
4157 optional_field = NULL;
4158
4159 guessed_type = guess_header_type(message, length, cur_token);
4160 type = MAILIMF_FIELD_NONE;
4161
4162 switch (guessed_type) {
4163 case MAILIMF_FIELD_ORIG_DATE:
4164 r = mailimf_orig_date_parse(message, length, &cur_token,
4165 &orig_date);
4166 if (r == MAILIMF_NO_ERROR)
4167 type = MAILIMF_FIELD_ORIG_DATE;
4168 else if (r == MAILIMF_ERROR_PARSE) {
4169 /* do nothing */
4170 }
4171 else {
4172 res = r;
4173 goto err;
4174 }
4175 break;
4176 case MAILIMF_FIELD_FROM:
4177 r = mailimf_from_parse(message, length, &cur_token,
4178 &from);
4179 if (r == MAILIMF_NO_ERROR)
4180 type = guessed_type;
4181 else if (r == MAILIMF_ERROR_PARSE) {
4182 /* do nothing */
4183 }
4184 else {
4185 res = r;
4186 goto err;
4187 }
4188 break;
4189 case MAILIMF_FIELD_SENDER:
4190 r = mailimf_sender_parse(message, length, &cur_token,
4191 &sender);
4192 if (r == MAILIMF_NO_ERROR)
4193 type = guessed_type;
4194 else if (r == MAILIMF_ERROR_PARSE) {
4195 /* do nothing */
4196 }
4197 else {
4198 res = r;
4199 goto err;
4200 }
4201 break;
4202 case MAILIMF_FIELD_REPLY_TO:
4203 r = mailimf_reply_to_parse(message, length, &cur_token,
4204 &reply_to);
4205 if (r == MAILIMF_NO_ERROR)
4206 type = guessed_type;
4207 else if (r == MAILIMF_ERROR_PARSE) {
4208 /* do nothing */
4209 }
4210 else {
4211 res = r;
4212 goto err;
4213 }
4214 break;
4215 case MAILIMF_FIELD_TO:
4216 r = mailimf_to_parse(message, length, &cur_token,
4217 &to);
4218 if (r == MAILIMF_NO_ERROR)
4219 type = guessed_type;
4220 else if (r == MAILIMF_ERROR_PARSE) {
4221 /* do nothing */
4222 }
4223 else {
4224 res = r;
4225 goto err;
4226 }
4227 break;
4228 case MAILIMF_FIELD_CC:
4229 r = mailimf_cc_parse(message, length, &cur_token,
4230 &cc);
4231 if (r == MAILIMF_NO_ERROR)
4232 type = guessed_type;
4233 else if (r == MAILIMF_ERROR_PARSE) {
4234 /* do nothing */
4235 }
4236 else {
4237 res = r;
4238 goto err;
4239 }
4240 break;
4241 case MAILIMF_FIELD_BCC:
4242 r = mailimf_bcc_parse(message, length, &cur_token,
4243 &bcc);
4244 if (r == MAILIMF_NO_ERROR)
4245 type = guessed_type;
4246 else if (r == MAILIMF_ERROR_PARSE) {
4247 /* do nothing */
4248 }
4249 else {
4250 res = r;
4251 goto err;
4252 }
4253 break;
4254 case MAILIMF_FIELD_MESSAGE_ID:
4255 r = mailimf_message_id_parse(message, length, &cur_token,
4256 &message_id);
4257 if (r == MAILIMF_NO_ERROR)
4258 type = guessed_type;
4259 else if (r == MAILIMF_ERROR_PARSE) {
4260 /* do nothing */
4261 }
4262 else {
4263 res = r;
4264 goto err;
4265 }
4266 break;
4267 case MAILIMF_FIELD_IN_REPLY_TO:
4268 r = mailimf_in_reply_to_parse(message, length, &cur_token,
4269 &in_reply_to);
4270 if (r == MAILIMF_NO_ERROR)
4271 type = guessed_type;
4272 else if (r == MAILIMF_ERROR_PARSE) {
4273 /* do nothing */
4274 }
4275 else {
4276 res = r;
4277 goto err;
4278 }
4279 break;
4280 case MAILIMF_FIELD_REFERENCES:
4281 r = mailimf_references_parse(message, length, &cur_token,
4282 &references);
4283 if (r == MAILIMF_NO_ERROR)
4284 type = guessed_type;
4285 else if (r == MAILIMF_ERROR_PARSE) {
4286 /* do nothing */
4287 }
4288 else {
4289 res = r;
4290 goto err;
4291 }
4292 break;
4293 case MAILIMF_FIELD_SUBJECT:
4294 r = mailimf_subject_parse(message, length, &cur_token,
4295 &subject);
4296 if (r == MAILIMF_NO_ERROR)
4297 type = guessed_type;
4298 else if (r == MAILIMF_ERROR_PARSE) {
4299 /* do nothing */
4300 }
4301 else {
4302 res = r;
4303 goto err;
4304 }
4305 break;
4306 case MAILIMF_FIELD_COMMENTS:
4307 r = mailimf_comments_parse(message, length, &cur_token,
4308 &comments);
4309 if (r == MAILIMF_NO_ERROR)
4310 type = guessed_type;
4311 else if (r == MAILIMF_ERROR_PARSE) {
4312 /* do nothing */
4313 }
4314 else {
4315 res = r;
4316 goto err;
4317 }
4318 break;
4319 case MAILIMF_FIELD_KEYWORDS:
4320 r = mailimf_keywords_parse(message, length, &cur_token,
4321 &keywords);
4322 if (r == MAILIMF_NO_ERROR)
4323 type = guessed_type;
4324 else if (r == MAILIMF_ERROR_PARSE) {
4325 /* do nothing */
4326 }
4327 else {
4328 res = r;
4329 goto err;
4330 }
4331 break;
4332 case MAILIMF_FIELD_RETURN_PATH:
4333 r = mailimf_return_parse(message, length, &cur_token,
4334 &return_path);
4335 if (r == MAILIMF_NO_ERROR)
4336 type = guessed_type;
4337 else if (r == MAILIMF_ERROR_PARSE) {
4338 /* do nothing */
4339 }
4340 else {
4341 res = r;
4342 goto err;
4343 }
4344 break;
4345 case MAILIMF_FIELD_RESENT_DATE:
4346 r = mailimf_resent_date_parse(message, length, &cur_token,
4347 &resent_date);
4348 if (r == MAILIMF_NO_ERROR)
4349 type = guessed_type;
4350 else if (r == MAILIMF_ERROR_PARSE) {
4351 /* do nothing */
4352 }
4353 else {
4354 res = r;
4355 goto err;
4356 }
4357 break;
4358 case MAILIMF_FIELD_RESENT_FROM:
4359 r = mailimf_resent_from_parse(message, length, &cur_token,
4360 &resent_from);
4361 if (r == MAILIMF_NO_ERROR)
4362 type = guessed_type;
4363 else if (r == MAILIMF_ERROR_PARSE) {
4364 /* do nothing */
4365 }
4366 else {
4367 res = r;
4368 goto err;
4369 }
4370 break;
4371 case MAILIMF_FIELD_RESENT_SENDER:
4372 r = mailimf_resent_sender_parse(message, length, &cur_token,
4373 &resent_sender);
4374 if (r == MAILIMF_NO_ERROR)
4375 type = guessed_type;
4376 else if (r == MAILIMF_ERROR_PARSE) {
4377 /* do nothing */
4378 }
4379 else {
4380 res = r;
4381 goto err;
4382 }
4383 break;
4384 case MAILIMF_FIELD_RESENT_TO:
4385 r = mailimf_resent_to_parse(message, length, &cur_token,
4386 &resent_to);
4387 if (r == MAILIMF_NO_ERROR)
4388 type = guessed_type;
4389 else if (r == MAILIMF_ERROR_PARSE) {
4390 /* do nothing */
4391 }
4392 else {
4393 res = r;
4394 goto err;
4395 }
4396 break;
4397 case MAILIMF_FIELD_RESENT_CC:
4398 r= mailimf_resent_cc_parse(message, length, &cur_token,
4399 &resent_cc);
4400 if (r == MAILIMF_NO_ERROR)
4401 type = guessed_type;
4402 else if (r == MAILIMF_ERROR_PARSE) {
4403 /* do nothing */
4404 }
4405 else {
4406 res = r;
4407 goto err;
4408 }
4409 break;
4410 case MAILIMF_FIELD_RESENT_BCC:
4411 r = mailimf_resent_bcc_parse(message, length, &cur_token,
4412 &resent_bcc);
4413 if (r == MAILIMF_NO_ERROR)
4414 type = guessed_type;
4415 else if (r == MAILIMF_ERROR_PARSE) {
4416 /* do nothing */
4417 }
4418 else {
4419 res = r;
4420 goto err;
4421 }
4422 break;
4423 case MAILIMF_FIELD_RESENT_MSG_ID:
4424 r = mailimf_resent_msg_id_parse(message, length, &cur_token,
4425 &resent_msg_id);
4426 if (r == MAILIMF_NO_ERROR)
4427 type = guessed_type;
4428 else if (r == MAILIMF_ERROR_PARSE) {
4429 /* do nothing */
4430 }
4431 else {
4432 res = r;
4433 goto err;
4434 }
4435 break;
4436 }
4437
4438 if (type == MAILIMF_FIELD_NONE) {
4439 r = mailimf_optional_field_parse(message, length, &cur_token,
4440 &optional_field);
4441 if (r != MAILIMF_NO_ERROR) {
4442 res = r;
4443 goto err;
4444 }
4445
4446 type = MAILIMF_FIELD_OPTIONAL_FIELD;
4447 }
4448
4449 field = mailimf_field_new(type, return_path, resent_date,
4450 resent_from, resent_sender, resent_to, resent_cc, resent_bcc,
4451 resent_msg_id, orig_date, from, sender, reply_to, to,
4452 cc, bcc, message_id, in_reply_to, references,
4453 subject, comments, keywords, optional_field);
4454 if (field == NULL) {
4455 res = MAILIMF_ERROR_MEMORY;
4456 goto free_field;
4457 }
4458
4459 * result = field;
4460 * index = cur_token;
4461
4462 return MAILIMF_NO_ERROR;
4463
4464 free_field:
4465 if (return_path != NULL)
4466 mailimf_return_free(return_path);
4467 if (resent_date != NULL)
4468 mailimf_orig_date_free(resent_date);
4469 if (resent_from != NULL)
4470 mailimf_from_free(resent_from);
4471 if (resent_sender != NULL)
4472 mailimf_sender_free(resent_sender);
4473 if (resent_to != NULL)
4474 mailimf_to_free(resent_to);
4475 if (resent_cc != NULL)
4476 mailimf_cc_free(resent_cc);
4477 if (resent_bcc != NULL)
4478 mailimf_bcc_free(resent_bcc);
4479 if (resent_msg_id != NULL)
4480 mailimf_message_id_free(resent_msg_id);
4481 if (orig_date != NULL)
4482 mailimf_orig_date_free(orig_date);
4483 if (from != NULL)
4484 mailimf_from_free(from);
4485 if (sender != NULL)
4486 mailimf_sender_free(sender);
4487 if (reply_to != NULL)
4488 mailimf_reply_to_free(reply_to);
4489 if (to != NULL)
4490 mailimf_to_free(to);
4491 if (cc != NULL)
4492 mailimf_cc_free(cc);
4493 if (bcc != NULL)
4494 mailimf_bcc_free(bcc);
4495 if (message_id != NULL)
4496 mailimf_message_id_free(message_id);
4497 if (in_reply_to != NULL)
4498 mailimf_in_reply_to_free(in_reply_to);
4499 if (references != NULL)
4500 mailimf_references_free(references);
4501 if (subject != NULL)
4502 mailimf_subject_free(subject);
4503 if (comments != NULL)
4504 mailimf_comments_free(comments);
4505 if (keywords != NULL)
4506 mailimf_keywords_free(keywords);
4507 if (optional_field != NULL)
4508 mailimf_optional_field_free(optional_field);
4509 err:
4510 return res;
4511}
4512
4513
4514/*
4515fields = *(delivering-info /
4516 orig-date /
4517 from /
4518 sender /
4519 reply-to /
4520 to /
4521 cc /
4522 bcc /
4523 message-id /
4524 in-reply-to /
4525 references /
4526 subject /
4527 comments /
4528 keywords /
4529 optional-field)
4530*/
4531
4532#if 0
4533int
4534mailimf_unparsed_fields_parse(const char * message, size_t length,
4535 size_t * index,
4536 struct mailimf_unparsed_fields ** result)
4537{
4538 size_t cur_token;
4539 clist * list;
4540 struct mailimf_unparsed_fields * fields;
4541 int r;
4542 int res;
4543
4544 cur_token = * index;
4545
4546 list = NULL;
4547
4548 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4549 &list,
4550 (mailimf_struct_parser *)
4551 mailimf_optional_field_parse,
4552 (mailimf_struct_destructor *)
4553 mailimf_optional_field_free);
4554 /*
4555 if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4556 res = r;
4557 goto err;
4558 }
4559 */
4560
4561 switch (r) {
4562 case MAILIMF_NO_ERROR:
4563 /* do nothing */
4564 break;
4565
4566 case MAILIMF_ERROR_PARSE:
4567 list = clist_new();
4568 if (list == NULL) {
4569 res = MAILIMF_ERROR_MEMORY;
4570 goto err;
4571 }
4572 break;
4573
4574 default:
4575 res = r;
4576 goto err;
4577 }
4578
4579 fields = mailimf_unparsed_fields_new(list);
4580 if (fields == NULL) {
4581 res = MAILIMF_ERROR_MEMORY;
4582 goto free;
4583 }
4584
4585 * result = fields;
4586 * index = cur_token;
4587
4588 return MAILIMF_NO_ERROR;
4589
4590 free:
4591 if (list != NULL) {
4592 clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL);
4593 clist_free(list);
4594 }
4595 err:
4596 return res;
4597}
4598#endif
4599
4600int mailimf_fields_parse(const char * message, size_t length,
4601 size_t * index,
4602 struct mailimf_fields ** result)
4603{
4604 size_t cur_token;
4605 clist * list;
4606 struct mailimf_fields * fields;
4607 int r;
4608 int res;
4609
4610 cur_token = * index;
4611
4612 list = NULL;
4613
4614 r = mailimf_struct_multiple_parse(message, length, &cur_token,
4615 &list,
4616 (mailimf_struct_parser *)
4617 mailimf_field_parse,
4618 (mailimf_struct_destructor *)
4619 mailimf_field_free);
4620 /*
4621 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
4622 res = r;
4623 goto err;
4624 }
4625 */
4626
4627 switch (r) {
4628 case MAILIMF_NO_ERROR:
4629 /* do nothing */
4630 break;
4631
4632 case MAILIMF_ERROR_PARSE:
4633 list = clist_new();
4634 if (list == NULL) {
4635 res = MAILIMF_ERROR_MEMORY;
4636 goto err;
4637 }
4638 break;
4639
4640 default:
4641 res = r;
4642 goto err;
4643 }
4644
4645 fields = mailimf_fields_new(list);
4646 if (fields == NULL) {
4647 res = MAILIMF_ERROR_MEMORY;
4648 goto free;
4649 }
4650
4651 * result = fields;
4652 * index = cur_token;
4653
4654 return MAILIMF_NO_ERROR;
4655
4656 free:
4657 if (list != NULL) {
4658 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
4659 clist_free(list);
4660 }
4661 err:
4662 return res;
4663}
4664
4665/*
4666orig-date = "Date:" date-time CRLF
4667*/
4668
4669
4670static int
4671mailimf_orig_date_parse(const char * message, size_t length,
4672 size_t * index, struct mailimf_orig_date ** result)
4673{
4674 struct mailimf_date_time * date_time;
4675 struct mailimf_orig_date * orig_date;
4676 size_t cur_token;
4677 int r;
4678 int res;
4679
4680 cur_token = * index;
4681
4682 r = mailimf_token_case_insensitive_parse(message, length,
4683 &cur_token, "Date:");
4684 if (r != MAILIMF_NO_ERROR) {
4685 res = r;
4686 goto err;
4687 }
4688
4689 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
4690 if (r != MAILIMF_NO_ERROR) {
4691 res = r;
4692 goto err;
4693 }
4694
4695 r = mailimf_ignore_unstructured_parse(message, length, &cur_token);
4696 if (r != MAILIMF_NO_ERROR) {
4697 res = r;
4698 goto free_date_time;
4699 }
4700
4701 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4702 if (r != MAILIMF_NO_ERROR) {
4703 res = r;
4704 goto free_date_time;
4705 }
4706
4707 orig_date = mailimf_orig_date_new(date_time);
4708 if (orig_date == NULL) {
4709 res = MAILIMF_ERROR_MEMORY;
4710 goto free_date_time;
4711 }
4712
4713 * result = orig_date;
4714 * index = cur_token;
4715
4716 return MAILIMF_NO_ERROR;
4717
4718 free_date_time:
4719 mailimf_date_time_free(date_time);
4720 err:
4721 return res;
4722}
4723
4724/*
4725from = "From:" mailbox-list CRLF
4726*/
4727
4728static int
4729mailimf_from_parse(const char * message, size_t length,
4730 size_t * index, struct mailimf_from ** result)
4731{
4732 struct mailimf_mailbox_list * mb_list;
4733 struct mailimf_from * from;
4734 size_t cur_token;
4735 int r;
4736 int res;
4737
4738 cur_token = * index;
4739
4740 r = mailimf_token_case_insensitive_parse(message, length,
4741 &cur_token, "From");
4742 if (r != MAILIMF_NO_ERROR) {
4743 res = r;
4744 goto err;
4745 }
4746
4747 r = mailimf_colon_parse(message, length, &cur_token);
4748 if (r != MAILIMF_NO_ERROR) {
4749 res = r;
4750 goto err;
4751 }
4752
4753 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
4754
4755 if (r != MAILIMF_NO_ERROR) {
4756 res = r;
4757 goto err;
4758 }
4759
4760 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4761 if (r != MAILIMF_NO_ERROR) {
4762 res = r;
4763 goto free_mb_list;
4764 }
4765
4766 from = mailimf_from_new(mb_list);
4767 if (from == NULL) {
4768 res = MAILIMF_ERROR_MEMORY;
4769 goto free_mb_list;
4770 }
4771
4772 * result = from;
4773 * index = cur_token;
4774
4775 return MAILIMF_NO_ERROR;
4776
4777 free_mb_list:
4778 mailimf_mailbox_list_free(mb_list);
4779 err:
4780 return res;
4781}
4782
4783/*
4784sender = "Sender:" mailbox CRLF
4785*/
4786
4787static int
4788mailimf_sender_parse(const char * message, size_t length,
4789 size_t * index, struct mailimf_sender ** result)
4790{
4791 struct mailimf_mailbox * mb;
4792 struct mailimf_sender * sender;
4793 size_t cur_token;
4794 int r;
4795 int res;
4796
4797 cur_token = * index;
4798
4799 r = mailimf_token_case_insensitive_parse(message, length,
4800 &cur_token, "Sender");
4801 if (r != MAILIMF_NO_ERROR) {
4802 res = r;
4803 goto err;
4804 }
4805
4806 r = mailimf_colon_parse(message, length, &cur_token);
4807 if (r != MAILIMF_NO_ERROR) {
4808 res = r;
4809 goto err;
4810 }
4811
4812 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
4813 if (r != MAILIMF_NO_ERROR) {
4814 res = r;
4815 goto err;
4816 }
4817
4818 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4819 if (r != MAILIMF_NO_ERROR) {
4820 res = r;
4821 goto free_mb;
4822 }
4823
4824 sender = mailimf_sender_new(mb);
4825 if (sender == NULL) {
4826 res = MAILIMF_ERROR_MEMORY;
4827 goto free_mb;
4828 }
4829
4830 * result = sender;
4831 * index = cur_token;
4832
4833 return MAILIMF_NO_ERROR;
4834
4835 free_mb:
4836 mailimf_mailbox_free(mb);
4837 err:
4838 return res;
4839}
4840
4841/*
4842reply-to = "Reply-To:" address-list CRLF
4843*/
4844
4845
4846static int
4847mailimf_reply_to_parse(const char * message, size_t length,
4848 size_t * index, struct mailimf_reply_to ** result)
4849{
4850 struct mailimf_address_list * addr_list;
4851 struct mailimf_reply_to * reply_to;
4852 size_t cur_token;
4853 int r;
4854 int res;
4855
4856 cur_token = * index;
4857
4858 r = mailimf_token_case_insensitive_parse(message, length,
4859 &cur_token, "Reply-To");
4860 if (r != MAILIMF_NO_ERROR) {
4861 res = r;
4862 goto err;
4863 }
4864
4865 r = mailimf_colon_parse(message, length, &cur_token);
4866 if (r != MAILIMF_NO_ERROR) {
4867 res = r;
4868 goto err;
4869 }
4870
4871 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4872 if (r != MAILIMF_NO_ERROR) {
4873 res = r;
4874 goto err;
4875 }
4876
4877 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4878 if (r != MAILIMF_NO_ERROR) {
4879 res = r;
4880 goto free_addr_list;
4881 }
4882
4883 reply_to = mailimf_reply_to_new(addr_list);
4884 if (reply_to == NULL) {
4885 res = MAILIMF_ERROR_MEMORY;
4886 goto free_addr_list;
4887 }
4888
4889 * result = reply_to;
4890 * index = cur_token;
4891
4892 return MAILIMF_NO_ERROR;
4893
4894 free_addr_list:
4895 mailimf_address_list_free(addr_list);
4896 err:
4897 return res;
4898}
4899
4900/*
4901to = "To:" address-list CRLF
4902*/
4903
4904static int
4905mailimf_to_parse(const char * message, size_t length,
4906 size_t * index, struct mailimf_to ** result)
4907{
4908 struct mailimf_address_list * addr_list;
4909 struct mailimf_to * to;
4910 size_t cur_token;
4911 int r;
4912 int res;
4913
4914 cur_token = * index;
4915
4916 r = mailimf_token_case_insensitive_parse(message, length,
4917 &cur_token, "To");
4918 if (r != MAILIMF_NO_ERROR) {
4919 res = r;
4920 goto err;
4921 }
4922
4923 r = mailimf_colon_parse(message, length, &cur_token);
4924 if (r != MAILIMF_NO_ERROR) {
4925 res = r;
4926 goto err;
4927 }
4928
4929 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4930 if (r != MAILIMF_NO_ERROR) {
4931 res = r;
4932 goto err;
4933 }
4934
4935 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4936 if (r != MAILIMF_NO_ERROR) {
4937 res = r;
4938 goto free_addr_list;
4939 }
4940
4941 to = mailimf_to_new(addr_list);
4942 if (to == NULL) {
4943 res = MAILIMF_ERROR_MEMORY;
4944 goto free_addr_list;
4945 }
4946
4947 * result = to;
4948 * index = cur_token;
4949
4950 return MAILIMF_NO_ERROR;
4951
4952 free_addr_list:
4953 mailimf_address_list_free(addr_list);
4954 err:
4955 return res;
4956}
4957
4958/*
4959cc = "Cc:" address-list CRLF
4960*/
4961
4962
4963static int
4964mailimf_cc_parse(const char * message, size_t length,
4965 size_t * index, struct mailimf_cc ** result)
4966{
4967 struct mailimf_address_list * addr_list;
4968 struct mailimf_cc * cc;
4969 size_t cur_token;
4970 int r;
4971 int res;
4972
4973 cur_token = * index;
4974
4975 r = mailimf_token_case_insensitive_parse(message, length,
4976 &cur_token, "Cc");
4977 if (r != MAILIMF_NO_ERROR) {
4978 res = r;
4979 goto err;
4980 }
4981
4982 r = mailimf_colon_parse(message, length, &cur_token);
4983 if (r != MAILIMF_NO_ERROR) {
4984 res = r;
4985 goto err;
4986 }
4987
4988 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
4989 if (r != MAILIMF_NO_ERROR) {
4990 res = r;
4991 goto err;
4992 }
4993
4994 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
4995 if (r != MAILIMF_NO_ERROR) {
4996 res = r;
4997 goto free_addr_list;
4998 }
4999
5000 cc = mailimf_cc_new(addr_list);
5001 if (cc == NULL) {
5002 res = MAILIMF_ERROR_MEMORY;
5003 goto free_addr_list;
5004 }
5005
5006 * result = cc;
5007 * index = cur_token;
5008
5009 return MAILIMF_NO_ERROR;
5010
5011 free_addr_list:
5012 mailimf_address_list_free(addr_list);
5013 err:
5014 return res;
5015}
5016
5017/*
5018bcc = "Bcc:" (address-list / [CFWS]) CRLF
5019*/
5020
5021
5022static int
5023mailimf_bcc_parse(const char * message, size_t length,
5024 size_t * index, struct mailimf_bcc ** result)
5025{
5026 struct mailimf_address_list * addr_list;
5027 struct mailimf_bcc * bcc;
5028 size_t cur_token;
5029 int r;
5030 int res;
5031
5032 cur_token = * index;
5033 addr_list = NULL;
5034
5035 r = mailimf_token_case_insensitive_parse(message, length,
5036 &cur_token, "Bcc");
5037 if (r != MAILIMF_NO_ERROR) {
5038 res = r;
5039 goto err;
5040 }
5041
5042 r = mailimf_colon_parse(message, length, &cur_token);
5043 if (r != MAILIMF_NO_ERROR) {
5044 res = r;
5045 goto err;
5046 }
5047
5048 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
5049 switch (r) {
5050 case MAILIMF_NO_ERROR:
5051 /* do nothing */
5052 break;
5053 case MAILIMF_ERROR_PARSE:
5054 r = mailimf_cfws_parse(message, length, &cur_token);
5055 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
5056 res = r;
5057 goto err;
5058 }
5059 break;
5060 default:
5061 res = r;
5062 goto err;
5063 }
5064
5065 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5066 if (r != MAILIMF_NO_ERROR) {
5067 res = r;
5068 goto free_addr_list;
5069 }
5070
5071 bcc = mailimf_bcc_new(addr_list);
5072 if (bcc == NULL) {
5073 res = MAILIMF_ERROR_MEMORY;
5074 goto free_addr_list;
5075 }
5076
5077 * result = bcc;
5078 * index = cur_token;
5079
5080 return MAILIMF_NO_ERROR;
5081
5082 free_addr_list:
5083 mailimf_address_list_free(addr_list);
5084 err:
5085 return res;
5086}
5087
5088/*
5089message-id = "Message-ID:" msg-id CRLF
5090*/
5091
5092static int mailimf_message_id_parse(const char * message, size_t length,
5093 size_t * index,
5094 struct mailimf_message_id ** result)
5095{
5096 char * value;
5097 size_t cur_token;
5098 struct mailimf_message_id * message_id;
5099 int r;
5100 int res;
5101
5102 cur_token = * index;
5103
5104 r = mailimf_token_case_insensitive_parse(message, length,
5105 &cur_token, "Message-ID");
5106 if (r != MAILIMF_NO_ERROR) {
5107 res = r;
5108 goto err;
5109 }
5110
5111 r = mailimf_colon_parse(message, length, &cur_token);
5112 if (r != MAILIMF_NO_ERROR) {
5113 res = r;
5114 goto err;
5115 }
5116
5117 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
5118 if (r != MAILIMF_NO_ERROR) {
5119 res = r;
5120 goto err;
5121 }
5122
5123 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5124 if (r != MAILIMF_NO_ERROR) {
5125 res = r;
5126 goto free_value;
5127 }
5128
5129 message_id = mailimf_message_id_new(value);
5130 if (message_id == NULL) {
5131 res = MAILIMF_ERROR_MEMORY;
5132 goto free_value;
5133 }
5134
5135 * result = message_id;
5136 * index = cur_token;
5137
5138 return MAILIMF_NO_ERROR;
5139
5140 free_value:
5141 mailimf_msg_id_free(value);
5142 err:
5143 return res;
5144}
5145
5146/*
5147in-reply-to = "In-Reply-To:" 1*msg-id CRLF
5148*/
5149
5150int mailimf_msg_id_list_parse(const char * message, size_t length,
5151 size_t * index, clist ** result)
5152{
5153 return mailimf_struct_multiple_parse(message, length, index,
5154 result,
5155 (mailimf_struct_parser *)
5156 mailimf_unstrict_msg_id_parse,
5157 (mailimf_struct_destructor *)
5158 mailimf_msg_id_free);
5159}
5160
5161static int mailimf_in_reply_to_parse(const char * message, size_t length,
5162 size_t * index,
5163 struct mailimf_in_reply_to ** result)
5164{
5165 struct mailimf_in_reply_to * in_reply_to;
5166 size_t cur_token;
5167 clist * msg_id_list;
5168 int res;
5169 int r;
5170
5171 cur_token = * index;
5172
5173 r = mailimf_token_case_insensitive_parse(message, length,
5174 &cur_token, "In-Reply-To");
5175 if (r != MAILIMF_NO_ERROR) {
5176 res = r;
5177 goto err;
5178 }
5179
5180 r = mailimf_colon_parse(message, length, &cur_token);
5181 if (r != MAILIMF_NO_ERROR) {
5182 res = r;
5183 goto err;
5184 }
5185
5186 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5187 if (r != MAILIMF_NO_ERROR) {
5188 res = r;
5189 goto err;
5190 }
5191
5192 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5193 if (r != MAILIMF_NO_ERROR) {
5194 res = r;
5195 goto free_list;
5196 }
5197
5198 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
5199 if (in_reply_to == NULL) {
5200 res = MAILIMF_ERROR_MEMORY;
5201 goto free_list;
5202 }
5203
5204 * result = in_reply_to;
5205 * index = cur_token;
5206
5207 return MAILIMF_NO_ERROR;
5208
5209 free_list:
5210 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5211 clist_free(msg_id_list);
5212 err:
5213 return res;
5214}
5215
5216/*
5217references = "References:" 1*msg-id CRLF
5218*/
5219
5220int mailimf_references_parse(const char * message, size_t length,
5221 size_t * index,
5222 struct mailimf_references ** result)
5223{
5224 struct mailimf_references * references;
5225 size_t cur_token;
5226 clist * msg_id_list;
5227 int r;
5228 int res;
5229
5230 cur_token = * index;
5231
5232 r = mailimf_token_case_insensitive_parse(message, length,
5233 &cur_token, "References");
5234 if (r != MAILIMF_NO_ERROR) {
5235 res = r;
5236 goto err;
5237 }
5238
5239 r = mailimf_colon_parse(message, length, &cur_token);
5240 if (r != MAILIMF_NO_ERROR) {
5241 res = r;
5242 goto err;
5243 }
5244
5245 r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list);
5246 if (r != MAILIMF_NO_ERROR) {
5247 res = r;
5248 goto err;
5249 }
5250
5251 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5252 if (r != MAILIMF_NO_ERROR) {
5253 res = r;
5254 goto free_list;
5255 }
5256
5257 references = mailimf_references_new(msg_id_list);
5258 if (references == NULL) {
5259 res = MAILIMF_ERROR_MEMORY;
5260 goto free_list;
5261 }
5262
5263 * result = references;
5264 * index = cur_token;
5265
5266 return MAILIMF_NO_ERROR;
5267
5268 free_list:
5269 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
5270 clist_free(msg_id_list);
5271 err:
5272 return res;
5273}
5274
5275/*
5276msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
5277*/
5278
5279int mailimf_msg_id_parse(const char * message, size_t length,
5280 size_t * index,
5281 char ** result)
5282{
5283 size_t cur_token;
5284#if 0
5285 char * id_left;
5286 char * id_right;
5287#endif
5288 char * msg_id;
5289 int r;
5290 int res;
5291
5292 cur_token = * index;
5293
5294 r = mailimf_cfws_parse(message, length, &cur_token);
5295 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5296 return r;
5297
5298 r = mailimf_lower_parse(message, length, &cur_token);
5299 if (r != MAILIMF_NO_ERROR) {
5300 res = r;
5301 goto err;
5302 }
5303
5304 r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id);
5305 if (r != MAILIMF_NO_ERROR) {
5306 res = r;
5307 goto err;
5308 }
5309
5310 r = mailimf_greater_parse(message, length, &cur_token);
5311 if (r != MAILIMF_NO_ERROR) {
5312 free(msg_id);
5313 res = r;
5314 goto err;
5315 }
5316
5317#if 0
5318 r = mailimf_id_left_parse(message, length, &cur_token, &id_left);
5319 if (r != MAILIMF_NO_ERROR) {
5320 res = r;
5321 goto err;
5322 }
5323
5324 r = mailimf_at_sign_parse(message, length, &cur_token);
5325 if (r != MAILIMF_NO_ERROR) {
5326 res = r;
5327 goto free_id_left;
5328 }
5329
5330 r = mailimf_id_right_parse(message, length, &cur_token, &id_right);
5331 if (r != MAILIMF_NO_ERROR) {
5332 res = r;
5333 goto free_id_left;
5334 }
5335
5336 r = mailimf_greater_parse(message, length, &cur_token);
5337 if (r != MAILIMF_NO_ERROR) {
5338 res = r;
5339 goto free_id_right;
5340 }
5341
5342 msg_id = malloc(strlen(id_left) + strlen(id_right) + 2);
5343 if (msg_id == NULL) {
5344 res = MAILIMF_ERROR_MEMORY;
5345 goto free_id_right;
5346 }
5347 strcpy(msg_id, id_left);
5348 strcat(msg_id, "@");
5349 strcat(msg_id, id_right);
5350
5351 mailimf_id_left_free(id_left);
5352 mailimf_id_right_free(id_right);
5353#endif
5354
5355 * result = msg_id;
5356 * index = cur_token;
5357
5358 return MAILIMF_NO_ERROR;
5359
5360#if 0
5361 free_id_right:
5362 mailimf_id_right_free(id_right);
5363 free_id_left:
5364 mailimf_id_left_free(id_left);
5365#endif
5366 /*
5367 free:
5368 mailimf_atom_free(msg_id);
5369 */
5370 err:
5371 return res;
5372}
5373
5374static int mailimf_parse_unwanted_msg_id(const char * message, size_t length,
5375 size_t * index)
5376{
5377 size_t cur_token;
5378 int r;
5379 char * word;
5380 int token_parsed;
5381
5382 cur_token = * index;
5383
5384 token_parsed = TRUE;
5385 while (token_parsed) {
5386 token_parsed = FALSE;
5387 r = mailimf_word_parse(message, length, &cur_token, &word);
5388 if (r == MAILIMF_NO_ERROR) {
5389 mailimf_word_free(word);
5390 token_parsed = TRUE;
5391 }
5392 else if (r == MAILIMF_ERROR_PARSE) {
5393 /* do nothing */
5394 }
5395 else
5396 return r;
5397 r = mailimf_semi_colon_parse(message, length, &cur_token);
5398 if (r == MAILIMF_NO_ERROR)
5399 token_parsed = TRUE;
5400 else if (r == MAILIMF_ERROR_PARSE) {
5401 /* do nothing */
5402 }
5403 else
5404 return r;
5405 r = mailimf_comma_parse(message, length, &cur_token);
5406 if (r == MAILIMF_NO_ERROR)
5407 token_parsed = TRUE;
5408 else if (r == MAILIMF_ERROR_PARSE) {
5409 /* do nothing */
5410 }
5411 else
5412 return r;
5413 r = mailimf_plus_parse(message, length, &cur_token);
5414 if (r == MAILIMF_NO_ERROR)
5415 token_parsed = TRUE;
5416 else if (r == MAILIMF_ERROR_PARSE) {
5417 /* do nothing */
5418 }
5419 else
5420 return r;
5421 r = mailimf_colon_parse(message, length, &cur_token);
5422 if (r == MAILIMF_NO_ERROR)
5423 token_parsed = TRUE;
5424 else if (r == MAILIMF_ERROR_PARSE) {
5425 /* do nothing */
5426 }
5427 else
5428 return r;
5429 r = mailimf_point_parse(message, length, &cur_token);
5430 if (r == MAILIMF_NO_ERROR)
5431 token_parsed = TRUE;
5432 else if (r == MAILIMF_ERROR_PARSE) {
5433 /* do nothing */
5434 }
5435 else
5436 return r;
5437 r = mailimf_at_sign_parse(message, length, &cur_token);
5438 if (r == MAILIMF_NO_ERROR)
5439 token_parsed = TRUE;
5440 else if (r == MAILIMF_ERROR_PARSE) {
5441 /* do nothing */
5442 }
5443 else
5444 return r;
5445 }
5446
5447 return MAILIMF_NO_ERROR;
5448}
5449
5450static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
5451 size_t * index,
5452 char ** result)
5453{
5454 char * msgid;
5455 size_t cur_token;
5456 int r;
5457
5458 cur_token = * index;
5459
5460 r = mailimf_cfws_parse(message, length, &cur_token);
5461 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
5462 return r;
5463
5464 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5465 if (r != MAILIMF_NO_ERROR)
5466 return r;
5467
5468 r = mailimf_msg_id_parse(message, length, &cur_token, &msgid);
5469 if (r != MAILIMF_NO_ERROR)
5470 return r;
5471
5472 r = mailimf_parse_unwanted_msg_id(message, length, &cur_token);
5473 if (r != MAILIMF_NO_ERROR)
5474 return r;
5475
5476 * result = msgid;
5477 * index = cur_token;
5478
5479 return MAILIMF_NO_ERROR;
5480}
5481
5482/*
5483id-left = dot-atom-text / no-fold-quote / obs-id-left
5484*/
5485
5486#if 0
5487static int mailimf_id_left_parse(const char * message, size_t length,
5488 size_t * index, char ** result)
5489{
5490 int r;
5491
5492 r = mailimf_dot_atom_text_parse(message, length, index, result);
5493 switch (r) {
5494 case MAILIMF_NO_ERROR:
5495 return MAILIMF_NO_ERROR;
5496 case MAILIMF_ERROR_PARSE:
5497 break;
5498 default:
5499 return r;
5500 }
5501
5502 r = mailimf_no_fold_quote_parse(message, length, index, result);
5503 if (r != MAILIMF_NO_ERROR)
5504 return r;
5505
5506 return MAILIMF_NO_ERROR;
5507}
5508#endif
5509
5510/*
5511id-right = dot-atom-text / no-fold-literal / obs-id-right
5512*/
5513
5514#if 0
5515static int mailimf_id_right_parse(const char * message, size_t length,
5516 size_t * index, char ** result)
5517{
5518 int r;
5519
5520 r = mailimf_dot_atom_text_parse(message, length, index, result);
5521 switch (r) {
5522 case MAILIMF_NO_ERROR:
5523 return MAILIMF_NO_ERROR;
5524 case MAILIMF_ERROR_PARSE:
5525 break;
5526 default:
5527 return r;
5528 }
5529
5530 r = mailimf_no_fold_literal_parse(message, length, index, result);
5531 if (r != MAILIMF_NO_ERROR)
5532 return r;
5533
5534 return MAILIMF_NO_ERROR;
5535}
5536#endif
5537
5538/*
5539no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
5540*/
5541
5542#if 0
5543static int mailimf_no_fold_quote_char_parse(const char * message, size_t length,
5544 size_t * index, char * result)
5545{
5546 char ch;
5547 size_t cur_token;
5548 int r;
5549
5550 cur_token = * index;
5551
5552#if 0
5553 r = mailimf_qtext_parse(message, length, &cur_token, &ch);
5554#endif
5555
5556 if (cur_token >= length)
5557 return MAILIMF_ERROR_PARSE;
5558
5559 if (is_qtext(message[cur_token])) {
5560 ch = message[cur_token];
5561 cur_token ++;
5562 }
5563 else {
5564 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5565
5566 if (r != MAILIMF_NO_ERROR)
5567 return r;
5568 }
5569
5570 * index = cur_token;
5571 * result = ch;
5572
5573 return MAILIMF_NO_ERROR;
5574}
5575#endif
5576
5577#if 0
5578static int mailimf_no_fold_quote_parse(const char * message, size_t length,
5579 size_t * index, char ** result)
5580{
5581 size_t cur_token;
5582 size_t begin;
5583 char ch;
5584 char * no_fold_quote;
5585 int r;
5586 int res;
5587
5588 begin = cur_token;
5589 r = mailimf_dquote_parse(message, length, &cur_token);
5590 if (r != MAILIMF_NO_ERROR) {
5591 res = r;
5592 goto err;
5593 }
5594
5595 while (1) {
5596 r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch);
5597 if (r == MAILIMF_NO_ERROR) {
5598 /* do nothing */
5599 }
5600 else if (r == MAILIMF_ERROR_PARSE)
5601 break;
5602 else {
5603 res = r;
5604 goto err;
5605 }
5606 }
5607
5608 r = mailimf_dquote_parse(message, length, &cur_token);
5609 if (r != MAILIMF_NO_ERROR) {
5610 res = r;
5611 goto err;
5612 }
5613
5614 /* no_fold_quote = strndup(message + begin, cur_token - begin); */
5615 no_fold_quote = malloc(cur_token - begin + 1);
5616 if (no_fold_quote == NULL) {
5617 res = MAILIMF_ERROR_MEMORY;
5618 goto err;
5619 }
5620 strncpy(no_fold_quote, message + begin, cur_token - begin);
5621 no_fold_quote[cur_token - begin] = '\0';
5622
5623 * result = no_fold_quote;
5624 * index = cur_token;
5625
5626 return MAILIMF_NO_ERROR;
5627
5628 err:
5629 return res;
5630}
5631#endif
5632
5633/*
5634no-fold-literal = "[" *(dtext / quoted-pair) "]"
5635*/
5636
5637#if 0
5638static inline int
5639mailimf_no_fold_literal_char_parse(const char * message, size_t length,
5640 size_t * index, char * result)
5641{
5642 char ch;
5643 size_t cur_token;
5644 int r;
5645
5646 cur_token = * index;
5647
5648#if 0
5649 r = mailimf_dtext_parse(message, length, &cur_token, &ch);
5650#endif
5651 if (cur_token >= length)
5652 return MAILIMF_ERROR_PARSE;
5653
5654 if (is_dtext(message[cur_token])) {
5655 ch = message[cur_token];
5656 cur_token ++;
5657 }
5658 else {
5659 r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
5660
5661 if (r != MAILIMF_NO_ERROR)
5662 return r;
5663 }
5664
5665 * index = cur_token;
5666 * result = ch;
5667
5668 return MAILIMF_NO_ERROR;
5669}
5670#endif
5671
5672#if 0
5673static int mailimf_no_fold_literal_parse(const char * message, size_t length,
5674 size_t * index, char ** result)
5675{
5676 size_t cur_token;
5677 size_t begin;
5678 char ch;
5679 char * no_fold_literal;
5680 int r;
5681 int res;
5682
5683 begin = cur_token;
5684 r = mailimf_obracket_parse(message, length, &cur_token);
5685 if (r != MAILIMF_NO_ERROR) {
5686 res = r;
5687 goto err;
5688 }
5689
5690 while (1) {
5691 r = mailimf_no_fold_literal_char_parse(message, length,
5692 &cur_token, &ch);
5693 if (r == MAILIMF_NO_ERROR) {
5694 /* do nothing */
5695 }
5696 else if (r == MAILIMF_ERROR_PARSE)
5697 break;
5698 else {
5699 res = r;
5700 goto err;
5701 }
5702 }
5703
5704 r = mailimf_cbracket_parse(message, length, &cur_token);
5705 if (r != MAILIMF_NO_ERROR) {
5706 res = r;
5707 goto err;
5708 }
5709
5710 /*
5711 no_fold_literal = strndup(message + begin, cur_token - begin);
5712 */
5713 no_fold_literal = malloc(cur_token - begin + 1);
5714 if (no_fold_literal == NULL) {
5715 res = MAILIMF_NO_ERROR;
5716 goto err;
5717 }
5718 strncpy(no_fold_literal, message + begin, cur_token - begin);
5719 no_fold_literal[cur_token - begin] = '\0';
5720
5721 * result = no_fold_literal;
5722 * index = cur_token;
5723
5724 return MAILIMF_NO_ERROR;
5725
5726 err:
5727 return res;
5728}
5729#endif
5730
5731/*
5732subject = "Subject:" unstructured CRLF
5733*/
5734
5735static int mailimf_subject_parse(const char * message, size_t length,
5736 size_t * index,
5737 struct mailimf_subject ** result)
5738{
5739 struct mailimf_subject * subject;
5740 char * value;
5741 size_t cur_token;
5742 int r;
5743 int res;
5744
5745 cur_token = * index;
5746
5747 r = mailimf_token_case_insensitive_parse(message, length,
5748 &cur_token, "Subject");
5749 if (r != MAILIMF_NO_ERROR) {
5750 res = r;
5751 goto err;
5752 }
5753
5754 r = mailimf_colon_parse(message, length, &cur_token);
5755 if (r != MAILIMF_NO_ERROR) {
5756 res = r;
5757 goto err;
5758 }
5759
5760 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5761 if (r != MAILIMF_NO_ERROR) {
5762 res = r;
5763 goto err;
5764 }
5765
5766 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5767 if (r != MAILIMF_NO_ERROR) {
5768 res = r;
5769 goto free_value;
5770 }
5771
5772 subject = mailimf_subject_new(value);
5773 if (subject == NULL) {
5774 res = MAILIMF_ERROR_MEMORY;
5775 goto free_value;
5776 }
5777
5778 * result = subject;
5779 * index = cur_token;
5780
5781 return MAILIMF_NO_ERROR;
5782
5783 free_value:
5784 mailimf_unstructured_free(value);
5785 err:
5786 return res;
5787}
5788
5789/*
5790comments = "Comments:" unstructured CRLF
5791*/
5792
5793static int mailimf_comments_parse(const char * message, size_t length,
5794 size_t * index,
5795 struct mailimf_comments ** result)
5796{
5797 struct mailimf_comments * comments;
5798 char * value;
5799 size_t cur_token;
5800 int r;
5801 int res;
5802
5803 cur_token = * index;
5804
5805 r = mailimf_token_case_insensitive_parse(message, length,
5806 &cur_token, "Comments");
5807 if (r != MAILIMF_NO_ERROR) {
5808 res = r;
5809 goto err;
5810 }
5811
5812 r = mailimf_colon_parse(message, length, &cur_token);
5813 if (r != MAILIMF_NO_ERROR) {
5814 res = r;
5815 goto err;
5816 }
5817
5818 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
5819 if (r != MAILIMF_NO_ERROR) {
5820 res = r;
5821 goto err;
5822 }
5823
5824 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5825 if (r != MAILIMF_NO_ERROR) {
5826 res = r;
5827 goto free_value;
5828 }
5829
5830 comments = mailimf_comments_new(value);
5831 if (comments == NULL) {
5832 res = MAILIMF_ERROR_MEMORY;
5833 goto free_value;
5834 }
5835
5836 * result = comments;
5837 * index = cur_token;
5838
5839 return MAILIMF_NO_ERROR;
5840
5841 free_value:
5842 mailimf_unstructured_free(value);
5843 err:
5844 return res;
5845}
5846
5847/*
5848keywords = "Keywords:" phrase *("," phrase) CRLF
5849*/
5850
5851static int mailimf_keywords_parse(const char * message, size_t length,
5852 size_t * index,
5853 struct mailimf_keywords ** result)
5854{
5855 struct mailimf_keywords * keywords;
5856 clist * list;
5857 size_t cur_token;
5858 int r;
5859 int res;
5860
5861 cur_token = * index;
5862
5863 r = mailimf_token_case_insensitive_parse(message, length,
5864 &cur_token, "Keywords");
5865 if (r != MAILIMF_NO_ERROR) {
5866 res = r;
5867 goto err;
5868 }
5869
5870 r = mailimf_colon_parse(message, length, &cur_token);
5871 if (r != MAILIMF_NO_ERROR) {
5872 res = r;
5873 goto err;
5874 }
5875
5876 r = mailimf_struct_list_parse(message, length, &cur_token,
5877 &list, ',',
5878 (mailimf_struct_parser *)
5879 mailimf_phrase_parse,
5880 (mailimf_struct_destructor *)
5881 mailimf_phrase_free);
5882 if (r != MAILIMF_NO_ERROR) {
5883 res = r;
5884 goto err;
5885 }
5886
5887 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5888 if (r != MAILIMF_NO_ERROR) {
5889 res = r;
5890 goto free_list;
5891 }
5892
5893 keywords = mailimf_keywords_new(list);
5894 if (keywords == NULL) {
5895 res = MAILIMF_ERROR_MEMORY;
5896 goto free_list;
5897 }
5898
5899 * result = keywords;
5900 * index = cur_token;
5901
5902 return MAILIMF_NO_ERROR;
5903
5904 free_list:
5905 clist_foreach(list, (clist_func) mailimf_phrase_free, NULL);
5906 clist_free(list);
5907 err:
5908 return res;
5909}
5910
5911/*
5912resent-date = "Resent-Date:" date-time CRLF
5913*/
5914
5915static int
5916mailimf_resent_date_parse(const char * message, size_t length,
5917 size_t * index, struct mailimf_orig_date ** result)
5918{
5919 struct mailimf_orig_date * orig_date;
5920 struct mailimf_date_time * date_time;
5921 size_t cur_token;
5922 int r;
5923 int res;
5924
5925 cur_token = * index;
5926
5927 r = mailimf_token_case_insensitive_parse(message, length,
5928 &cur_token, "Resent-Date");
5929 if (r != MAILIMF_NO_ERROR) {
5930 res = r;
5931 goto err;
5932 }
5933
5934 r = mailimf_colon_parse(message, length, &cur_token);
5935 if (r != MAILIMF_NO_ERROR) {
5936 res = r;
5937 goto err;
5938 }
5939
5940 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
5941 if (r != MAILIMF_NO_ERROR) {
5942 res = r;
5943 goto err;
5944 }
5945
5946 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
5947 if (r != MAILIMF_NO_ERROR) {
5948 res = r;
5949 goto free_date_time;
5950 }
5951
5952 orig_date = mailimf_orig_date_new(date_time);
5953 if (orig_date == NULL) {
5954 res = MAILIMF_ERROR_MEMORY;
5955 goto free_date_time;
5956 }
5957
5958 * result = orig_date;
5959 * index = cur_token;
5960
5961 return MAILIMF_NO_ERROR;
5962
5963 free_date_time:
5964 mailimf_date_time_free(date_time);
5965 err:
5966 return res;
5967}
5968
5969/*
5970resent-from = "Resent-From:" mailbox-list CRLF
5971*/
5972
5973static int
5974mailimf_resent_from_parse(const char * message, size_t length,
5975 size_t * index, struct mailimf_from ** result)
5976{
5977 struct mailimf_mailbox_list * mb_list;
5978 struct mailimf_from * from;
5979 size_t cur_token;
5980 int r;
5981 int res;
5982
5983 cur_token = * index;
5984
5985 r = mailimf_token_case_insensitive_parse(message, length,
5986 &cur_token, "Resent-From");
5987 if (r != MAILIMF_NO_ERROR) {
5988 res = r;
5989 goto err;
5990 }
5991
5992 r = mailimf_colon_parse(message, length, &cur_token);
5993 if (r != MAILIMF_NO_ERROR) {
5994 res = r;
5995 goto err;
5996 }
5997
5998 r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list);
5999 if (r != MAILIMF_NO_ERROR) {
6000 res = r;
6001 goto err;
6002 }
6003
6004 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6005 if (r != MAILIMF_NO_ERROR) {
6006 res = r;
6007 goto free_mb_list;
6008 }
6009
6010 from = mailimf_from_new(mb_list);
6011 if (from == NULL) {
6012 res = MAILIMF_ERROR_MEMORY;
6013 goto free_mb_list;
6014 }
6015
6016 * result = from;
6017 * index = cur_token;
6018
6019 return MAILIMF_NO_ERROR;
6020
6021 free_mb_list:
6022 mailimf_mailbox_list_free(mb_list);
6023 err:
6024 return res;
6025}
6026
6027/*
6028resent-sender = "Resent-Sender:" mailbox CRLF
6029*/
6030
6031static int
6032mailimf_resent_sender_parse(const char * message, size_t length,
6033 size_t * index, struct mailimf_sender ** result)
6034{
6035 struct mailimf_mailbox * mb;
6036 struct mailimf_sender * sender;
6037 size_t cur_token;
6038 int r;
6039 int res;
6040
6041 cur_token = length;
6042
6043 r = mailimf_token_case_insensitive_parse(message, length,
6044 &cur_token, "Resent-Sender");
6045 if (r != MAILIMF_NO_ERROR) {
6046 res = r;
6047 goto err;
6048 }
6049
6050 r = mailimf_colon_parse(message, length, &cur_token);
6051 if (r != MAILIMF_NO_ERROR) {
6052 res = r;
6053 goto err;
6054 }
6055
6056 r = mailimf_mailbox_parse(message, length, &cur_token, &mb);
6057 if (r != MAILIMF_NO_ERROR) {
6058 res = r;
6059 goto err;
6060 }
6061
6062 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6063 if (r != MAILIMF_NO_ERROR) {
6064 res = r;
6065 goto free_mb;
6066 }
6067
6068 sender = mailimf_sender_new(mb);
6069 if (sender == NULL) {
6070 res = MAILIMF_ERROR_MEMORY;
6071 goto free_mb;
6072 }
6073
6074 * result = sender;
6075 * index = cur_token;
6076
6077 return MAILIMF_NO_ERROR;
6078
6079 free_mb:
6080 mailimf_mailbox_free(mb);
6081 err:
6082 return res;
6083}
6084
6085/*
6086resent-to = "Resent-To:" address-list CRLF
6087*/
6088
6089static int
6090mailimf_resent_to_parse(const char * message, size_t length,
6091 size_t * index, struct mailimf_to ** result)
6092{
6093 struct mailimf_address_list * addr_list;
6094 struct mailimf_to * to;
6095 size_t cur_token;
6096 int r;
6097 int res;
6098
6099 cur_token = * index;
6100
6101 r = mailimf_token_case_insensitive_parse(message, length,
6102 &cur_token, "Resent-To");
6103 if (r != MAILIMF_NO_ERROR) {
6104 res = r;
6105 goto err;
6106 }
6107
6108 r = mailimf_colon_parse(message, length, &cur_token);
6109 if (r != MAILIMF_NO_ERROR) {
6110 res = r;
6111 goto err;
6112 }
6113
6114 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6115 if (r != MAILIMF_NO_ERROR) {
6116 res = r;
6117 goto err;
6118 }
6119
6120 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6121 if (r != MAILIMF_NO_ERROR) {
6122 res = r;
6123 goto free_addr_list;
6124 }
6125
6126 to = mailimf_to_new(addr_list);
6127 if (to == NULL) {
6128 res = MAILIMF_ERROR_MEMORY;
6129 goto free_addr_list;
6130 }
6131
6132 * result = to;
6133 * index = cur_token;
6134
6135 return MAILIMF_NO_ERROR;
6136
6137 free_addr_list:
6138 mailimf_address_list_free(addr_list);
6139 err:
6140 return res;
6141}
6142
6143/*
6144resent-cc = "Resent-Cc:" address-list CRLF
6145*/
6146
6147static int
6148mailimf_resent_cc_parse(const char * message, size_t length,
6149 size_t * index, struct mailimf_cc ** result)
6150{
6151 struct mailimf_address_list * addr_list;
6152 struct mailimf_cc * cc;
6153 size_t cur_token;
6154 int r;
6155 int res;
6156
6157 cur_token = * index;
6158
6159 r = mailimf_token_case_insensitive_parse(message, length,
6160 &cur_token, "Resent-Cc");
6161 if (r != MAILIMF_NO_ERROR) {
6162 res = r;
6163 goto err;
6164 }
6165
6166 r = mailimf_colon_parse(message, length, &cur_token);
6167 if (r != MAILIMF_NO_ERROR) {
6168 res = r;
6169 goto err;
6170 }
6171
6172 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6173 if (r != MAILIMF_NO_ERROR) {
6174 res = r;
6175 goto err;
6176 }
6177
6178 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6179 if (r != MAILIMF_NO_ERROR) {
6180 res = r;
6181 goto free_addr_list;
6182 }
6183
6184 cc = mailimf_cc_new(addr_list);
6185 if (cc == NULL) {
6186 res = MAILIMF_ERROR_MEMORY;
6187 goto free_addr_list;
6188 }
6189
6190 * result = cc;
6191 * index = cur_token;
6192
6193 return MAILIMF_NO_ERROR;
6194
6195 free_addr_list:
6196 mailimf_address_list_free(addr_list);
6197 err:
6198 return res;
6199}
6200
6201/*
6202resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
6203*/
6204
6205static int
6206mailimf_resent_bcc_parse(const char * message, size_t length,
6207 size_t * index, struct mailimf_bcc ** result)
6208{
6209 struct mailimf_address_list * addr_list;
6210 struct mailimf_bcc * bcc;
6211 size_t cur_token;
6212 int r;
6213 int res;
6214
6215 cur_token = * index;
6216 bcc = NULL;
6217
6218 r = mailimf_token_case_insensitive_parse(message, length,
6219 &cur_token, "Resent-Bcc");
6220 if (r != MAILIMF_NO_ERROR) {
6221 res = r;
6222 goto err;
6223 }
6224
6225 r = mailimf_colon_parse(message, length, &cur_token);
6226 if (r != MAILIMF_NO_ERROR) {
6227 res = r;
6228 goto err;
6229 }
6230
6231 r = mailimf_address_list_parse(message, length, &cur_token, &addr_list);
6232 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6233 res = r;
6234 goto err;
6235 }
6236
6237 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6238 if (r != MAILIMF_NO_ERROR) {
6239 res = r;
6240 goto free_addr_list;
6241 }
6242
6243 bcc = mailimf_bcc_new(addr_list);
6244 if (bcc == NULL) {
6245 res = MAILIMF_ERROR_MEMORY;
6246 goto free_addr_list;
6247 }
6248
6249 * result = bcc;
6250 * index = cur_token;
6251
6252 return TRUE;
6253
6254 free_addr_list:
6255 mailimf_address_list_free(addr_list);
6256 err:
6257 return res;
6258}
6259
6260/*
6261resent-msg-id = "Resent-Message-ID:" msg-id CRLF
6262*/
6263
6264static int
6265mailimf_resent_msg_id_parse(const char * message, size_t length,
6266 size_t * index,
6267 struct mailimf_message_id ** result)
6268{
6269 char * value;
6270 size_t cur_token;
6271 struct mailimf_message_id * message_id;
6272 int r;
6273 int res;
6274
6275 cur_token = * index;
6276
6277 r = mailimf_token_case_insensitive_parse(message, length,
6278 &cur_token, "Resent-Message-ID");
6279 if (r != MAILIMF_NO_ERROR) {
6280 res = r;
6281 goto err;
6282 }
6283
6284 r = mailimf_colon_parse(message, length, &cur_token);
6285 if (r != MAILIMF_NO_ERROR) {
6286 res = r;
6287 goto err;
6288 }
6289
6290 r = mailimf_msg_id_parse(message, length, &cur_token, &value);
6291 if (r != MAILIMF_NO_ERROR) {
6292 res = r;
6293 goto err;
6294 }
6295
6296 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6297 if (r != MAILIMF_NO_ERROR) {
6298 res = r;
6299 goto free_value;
6300 }
6301
6302 message_id = mailimf_message_id_new(value);
6303 if (message_id == NULL) {
6304 res = MAILIMF_ERROR_MEMORY;
6305 goto free_value;
6306 }
6307
6308 * result = message_id;
6309 * index = cur_token;
6310
6311 return MAILIMF_NO_ERROR;
6312
6313 free_value:
6314 mailimf_msg_id_free(value);
6315 err:
6316 return res;
6317}
6318
6319/*
6320trace = [return]
6321 1*received
6322*/
6323
6324#if 0
6325static int mailimf_trace_parse(const char * message, size_t length,
6326 size_t * index,
6327 struct mailimf_trace ** result)
6328{
6329 size_t cur_token;
6330 struct mailimf_return * return_path;
6331 clist * received_list;
6332 struct mailimf_trace * trace;
6333 int r;
6334 int res;
6335
6336 cur_token = * index;
6337 return_path = NULL;
6338 received_list = NULL;
6339
6340 r = mailimf_return_parse(message, length, &cur_token, &return_path);
6341 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6342 res = r;
6343 goto err;
6344 }
6345
6346 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6347 &received_list,
6348 (mailimf_struct_parser *)
6349 mailimf_received_parse,
6350 (mailimf_struct_destructor *)
6351 mailimf_received_free);
6352 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6353 res = r;
6354 goto err;
6355 }
6356
6357 if ((received_list == NULL) && (return_path == NULL)) {
6358 res = MAILIMF_ERROR_PARSE;
6359 goto free_return;
6360 }
6361
6362 trace = mailimf_trace_new(return_path, received_list);
6363 if (trace == NULL) {
6364 res = MAILIMF_ERROR_MEMORY;
6365 goto free_list;
6366 }
6367
6368 * result = trace;
6369 * index = cur_token;
6370
6371 return MAILIMF_NO_ERROR;
6372
6373 free_list:
6374 clist_foreach(received_list, (clist_func) mailimf_received_free, NULL);
6375 clist_free(received_list);
6376 free_return:
6377 if (return_path != NULL)
6378 mailimf_return_free(return_path);
6379 err:
6380 return res;
6381}
6382#endif
6383
6384/*
6385return = "Return-Path:" path CRLF
6386*/
6387
6388static int mailimf_return_parse(const char * message, size_t length,
6389 size_t * index,
6390 struct mailimf_return ** result)
6391{
6392 struct mailimf_path * path;
6393 struct mailimf_return * return_path;
6394 size_t cur_token;
6395 int r;
6396 int res;
6397
6398 cur_token = * index;
6399
6400 r = mailimf_token_case_insensitive_parse(message, length,
6401 &cur_token, "Return-Path");
6402 if (r != MAILIMF_NO_ERROR) {
6403 res = r;
6404 goto err;
6405 }
6406
6407 r = mailimf_colon_parse(message, length, &cur_token);
6408 if (r != MAILIMF_NO_ERROR) {
6409 res = r;
6410 goto err;
6411 }
6412
6413 r = mailimf_path_parse(message, length, &cur_token, &path);
6414 if ( r!= MAILIMF_NO_ERROR) {
6415 res = r;
6416 goto err;
6417 }
6418
6419 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6420 if (r != MAILIMF_NO_ERROR) {
6421 res = r;
6422 goto free_path;
6423 }
6424
6425 return_path = mailimf_return_new(path);
6426 if (return_path == NULL) {
6427 res = MAILIMF_ERROR_MEMORY;
6428 goto free_path;
6429 }
6430
6431 * result = return_path;
6432 * index = cur_token;
6433
6434 return MAILIMF_NO_ERROR;
6435
6436 free_path:
6437 mailimf_path_free(path);
6438 err:
6439 return res;
6440}
6441
6442/*
6443path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
6444 obs-path
6445*/
6446
6447static int mailimf_path_parse(const char * message, size_t length,
6448 size_t * index, struct mailimf_path ** result)
6449{
6450 size_t cur_token;
6451 char * addr_spec;
6452 struct mailimf_path * path;
6453 int res;
6454 int r;
6455
6456 cur_token = * index;
6457 addr_spec = NULL;
6458
6459 r = mailimf_cfws_parse(message, length, &cur_token);
6460 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6461 res = r;
6462 goto err;
6463 }
6464
6465 r = mailimf_lower_parse(message, length, &cur_token);
6466 if (r != MAILIMF_NO_ERROR) {
6467 res = r;
6468 goto err;
6469 }
6470
6471 r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec);
6472 switch (r) {
6473 case MAILIMF_NO_ERROR:
6474 break;
6475 case MAILIMF_ERROR_PARSE:
6476 r = mailimf_cfws_parse(message, length, &cur_token);
6477 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6478 res = r;
6479 goto err;
6480 }
6481 break;
6482 default:
6483 return r;
6484 }
6485
6486 r = mailimf_greater_parse(message, length, &cur_token);
6487 if (r != MAILIMF_NO_ERROR) {
6488 res = r;
6489 goto err;
6490 }
6491
6492 path = mailimf_path_new(addr_spec);
6493 if (path == NULL) {
6494 res = MAILIMF_ERROR_MEMORY;
6495 goto free_addr_spec;
6496 }
6497
6498 * index = cur_token;
6499 * result = path;
6500
6501 return MAILIMF_NO_ERROR;
6502
6503 free_addr_spec:
6504 if (addr_spec == NULL)
6505 mailimf_addr_spec_free(addr_spec);
6506 err:
6507 return res;
6508}
6509
6510/*
6511received = "Received:" name-val-list ";" date-time CRLF
6512*/
6513
6514#if 0
6515static int mailimf_received_parse(const char * message, size_t length,
6516 size_t * index,
6517 struct mailimf_received ** result)
6518{
6519 size_t cur_token;
6520 struct mailimf_received * received;
6521 struct mailimf_name_val_list * name_val_list;
6522 struct mailimf_date_time * date_time;
6523 int r;
6524 int res;
6525
6526 cur_token = * index;
6527
6528 r = mailimf_token_case_insensitive_parse(message, length,
6529 &cur_token, "Received");
6530 if (r != MAILIMF_NO_ERROR) {
6531 res = r;
6532 goto err;
6533 }
6534
6535 r = mailimf_colon_parse(message, length, &cur_token);
6536 if (r != MAILIMF_NO_ERROR) {
6537 res = r;
6538 goto err;
6539 }
6540
6541 r = mailimf_name_val_list_parse(message, length,
6542 &cur_token, &name_val_list);
6543 if (r != MAILIMF_NO_ERROR) {
6544 res = r;
6545 goto err;
6546 }
6547
6548 r = mailimf_semi_colon_parse(message, length, &cur_token);
6549 if (r != MAILIMF_NO_ERROR) {
6550 res = r;
6551 goto free_name_val_list;
6552 }
6553
6554 r = mailimf_date_time_parse(message, length, &cur_token, &date_time);
6555 if (r != MAILIMF_NO_ERROR) {
6556 res = r;
6557 goto free_name_val_list;
6558 }
6559
6560 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6561 if (r != MAILIMF_NO_ERROR) {
6562 res = r;
6563 goto free_date_time;
6564 }
6565
6566 received = mailimf_received_new(name_val_list, date_time);
6567 if (received == NULL) {
6568 res = MAILIMF_ERROR_MEMORY;
6569 goto free_date_time;
6570 }
6571
6572 * index = cur_token;
6573 * result = received;
6574
6575 return MAILIMF_NO_ERROR;
6576
6577 free_date_time:
6578 mailimf_date_time_free(date_time);
6579 free_name_val_list:
6580 mailimf_name_val_list_free(name_val_list);
6581 err:
6582 return res;
6583}
6584#endif
6585
6586/*
6587name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
6588*/
6589
6590#if 0
6591static int
6592mailimf_name_val_list_parse(const char * message, size_t length,
6593 size_t * index,
6594 struct mailimf_name_val_list ** result)
6595{
6596 size_t cur_token;
6597 struct mailimf_name_val_pair * pair;
6598 struct mailimf_name_val_list * name_val_list;
6599 clist* list;
6600 int res;
6601 int r;
6602
6603 cur_token = * index;
6604 list = NULL;
6605
6606 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6607
6608 if (r == MAILIMF_NO_ERROR){
6609 size_t final_token;
6610
6611 list = clist_new();
6612 if (list == NULL) {
6613 mailimf_name_val_pair_free(pair);
6614 res = MAILIMF_ERROR_MEMORY;
6615 goto err;
6616 }
6617
6618 r = clist_append(list, pair);
6619 if (r < 0) {
6620 mailimf_name_val_pair_free(pair);
6621 res = MAILIMF_ERROR_MEMORY;
6622 goto free_list;
6623 }
6624
6625 final_token = cur_token;
6626
6627 while (1) {
6628 r = mailimf_cfws_parse(message, length, &cur_token);
6629 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6630 res = r;
6631 goto free_list;
6632 }
6633
6634 r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair);
6635 if (r == MAILIMF_NO_ERROR) {
6636 /* do nothing */
6637 }
6638 else if (r == MAILIMF_ERROR_PARSE)
6639 break;
6640 else {
6641 res = r;
6642 goto free_list;
6643 }
6644
6645 r = clist_append(list, pair);
6646 if (r < 0) {
6647 mailimf_name_val_pair_free(pair);
6648 res = MAILIMF_ERROR_MEMORY;
6649 goto free_list;
6650 }
6651
6652 final_token = cur_token;
6653 }
6654 cur_token = final_token;
6655 }
6656
6657 name_val_list = mailimf_name_val_list_new(list);
6658 if (name_val_list == NULL) {
6659 res = MAILIMF_ERROR_MEMORY;
6660 goto free_list;
6661 }
6662
6663 * index = cur_token;
6664 * result = name_val_list;
6665
6666 return MAILIMF_NO_ERROR;
6667
6668 free_list:
6669 if (list != NULL) {
6670 clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL);
6671 clist_free(list);
6672 }
6673 err:
6674 return res;
6675}
6676#endif
6677
6678/*
6679name-val-pair = item-name CFWS item-value
6680*/
6681
6682#if 0
6683static int
6684mailimf_name_val_pair_parse(const char * message, size_t length,
6685 size_t * index,
6686 struct mailimf_name_val_pair ** result)
6687{
6688 size_t cur_token;
6689 char * item_name;
6690 struct mailimf_item_value * item_value;
6691 struct mailimf_name_val_pair * name_val_pair;
6692 int r;
6693 int res;
6694
6695 cur_token = * index;
6696
6697 r = mailimf_cfws_parse(message, length, &cur_token);
6698 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
6699 res = r;
6700 goto err;
6701 }
6702
6703 r = mailimf_item_name_parse(message, length, &cur_token, &item_name);
6704 if (r != MAILIMF_NO_ERROR) {
6705 res = r;
6706 goto err;
6707 }
6708
6709 r = mailimf_cfws_parse(message, length, &cur_token);
6710 if (r != MAILIMF_NO_ERROR) {
6711 res = r;
6712 goto free_item_name;
6713 }
6714
6715 r = mailimf_item_value_parse(message, length, &cur_token, &item_value);
6716 if (r != MAILIMF_NO_ERROR) {
6717 res = r;
6718 goto free_item_name;
6719 }
6720
6721 name_val_pair = mailimf_name_val_pair_new(item_name, item_value);
6722 if (name_val_pair == NULL) {
6723 res = MAILIMF_ERROR_MEMORY;
6724 goto free_item_value;
6725 }
6726
6727 * result = name_val_pair;
6728 * index = cur_token;
6729
6730 return MAILIMF_NO_ERROR;
6731
6732 free_item_value:
6733 mailimf_item_value_free(item_value);
6734 free_item_name:
6735 mailimf_item_name_free(item_name);
6736 err:
6737 return res;
6738}
6739#endif
6740
6741/*
6742item-name = ALPHA *(["-"] (ALPHA / DIGIT))
6743*/
6744
6745#if 0
6746static int mailimf_item_name_parse(const char * message, size_t length,
6747 size_t * index, char ** result)
6748{
6749 size_t cur_token;
6750 size_t begin;
6751 char * item_name;
6752 char ch;
6753 int digit;
6754 int r;
6755 int res;
6756
6757 cur_token = * index;
6758
6759 begin = cur_token;
6760
6761 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6762 if (r != MAILIMF_NO_ERROR) {
6763 res = r;
6764 goto err;
6765 }
6766
6767 while (1) {
6768 int minus_sign;
6769
6770 minus_sign = mailimf_minus_parse(message, length, &cur_token);
6771
6772 r = mailimf_alpha_parse(message, length, &cur_token, &ch);
6773 if (r == MAILIMF_ERROR_PARSE)
6774 r = mailimf_digit_parse(message, length, &cur_token, &digit);
6775
6776 if (r == MAILIMF_NO_ERROR) {
6777 /* do nothing */
6778 }
6779 if (r == MAILIMF_ERROR_PARSE)
6780 break;
6781 else if (r != MAILIMF_NO_ERROR) {
6782 res = r;
6783 goto err;
6784 }
6785 }
6786
6787 item_name = strndup(message + begin, cur_token - begin);
6788 if (item_name == NULL) {
6789 res = MAILIMF_ERROR_MEMORY;
6790 goto err;
6791 }
6792
6793 * index = cur_token;
6794 * result = item_name;
6795
6796 return MAILIMF_NO_ERROR;
6797
6798 err:
6799 return res;
6800}
6801#endif
6802
6803/*
6804item-value = 1*angle-addr / addr-spec /
6805 atom / domain / msg-id
6806*/
6807
6808#if 0
6809static int is_item_value_atext(char ch)
6810{
6811 switch (ch) {
6812 case '\t':
6813 case ' ':
6814 case '\r':
6815 case '\n':
6816 case ';':
6817 return FALSE;
6818 default:
6819 return TRUE;
6820 }
6821}
6822
6823static int mailimf_item_value_atom_parse(const char * message, size_t length,
6824 size_t * index, char ** result)
6825{
6826 char * atom;
6827 size_t cur_token;
6828 int r;
6829
6830 cur_token = * index;
6831
6832 r = mailimf_cfws_parse(message, length, &cur_token);
6833 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6834 return r;
6835
6836 r = mailimf_custom_string_parse(message, length, &cur_token,
6837 &atom, is_item_value_atext);
6838 if (r != MAILIMF_NO_ERROR)
6839 return r;
6840
6841 r = mailimf_cfws_parse(message, length, &cur_token);
6842 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
6843 return r;
6844
6845 * index = cur_token;
6846 * result = atom;
6847
6848 return MAILIMF_NO_ERROR;
6849}
6850
6851static int mailimf_item_value_parse(const char * message, size_t length,
6852 size_t * index,
6853 struct mailimf_item_value ** result)
6854{
6855 size_t cur_token;
6856 clist * angle_addr_list;
6857 char * addr_spec;
6858 char * atom;
6859 char * domain;
6860 char * msg_id;
6861 int type;
6862 struct mailimf_item_value * item_value;
6863 int r;
6864 int res;
6865
6866 cur_token = * index;
6867
6868 angle_addr_list = NULL;
6869 addr_spec = NULL;
6870 atom = NULL;
6871 domain = NULL;
6872 msg_id = NULL;
6873
6874 r = mailimf_struct_multiple_parse(message, length, &cur_token,
6875 &angle_addr_list,
6876 (mailimf_struct_parser *)
6877 mailimf_angle_addr_parse,
6878 (mailimf_struct_destructor *)
6879 mailimf_angle_addr_free);
6880 if (r == MAILIMF_NO_ERROR)
6881 type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST;
6882
6883 if (r == MAILIMF_ERROR_PARSE) {
6884 r = mailimf_addr_spec_parse(message, length, &cur_token,
6885 &addr_spec);
6886 if (r == MAILIMF_NO_ERROR)
6887 type = MAILIMF_ITEM_VALUE_ADDR_SPEC;
6888 }
6889
6890 if (r == MAILIMF_ERROR_PARSE) {
6891 r = mailimf_msg_id_parse(message, length, &cur_token,
6892 &msg_id);
6893 if (r == MAILIMF_NO_ERROR)
6894 type = MAILIMF_ITEM_VALUE_MSG_ID;
6895 }
6896
6897 /*
6898 else if (mailimf_domain_parse(message, length, &cur_token,
6899 &domain))
6900 type = MAILIMF_ITEM_VALUE_DOMAIN;
6901 */
6902 /*
6903 else if (mailimf_atom_parse(message, length, &cur_token,
6904 &atom))
6905 type = MAILIMF_ITEM_VALUE_ATOM;
6906 */
6907
6908 if (r == MAILIMF_ERROR_PARSE) {
6909 r = mailimf_item_value_atom_parse(message, length, &cur_token,
6910 &atom);
6911 if (r == MAILIMF_NO_ERROR)
6912 type = MAILIMF_ITEM_VALUE_ATOM;
6913 }
6914
6915 if (r != MAILIMF_NO_ERROR) {
6916 res = r;
6917 goto err;
6918 }
6919
6920 item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec,
6921 atom, domain, msg_id);
6922 if (item_value == NULL) {
6923 res = MAILIMF_ERROR_MEMORY;
6924 goto free;
6925 }
6926
6927 * result = item_value;
6928 * index = cur_token;
6929
6930 return MAILIMF_NO_ERROR;
6931
6932 free:
6933 if (angle_addr_list != NULL) {
6934 clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL);
6935 clist_free(angle_addr_list);
6936 }
6937 if (addr_spec != NULL)
6938 mailimf_addr_spec_free(addr_spec);
6939 if (atom != NULL)
6940 mailimf_atom_free(atom);
6941 if (domain != NULL)
6942 mailimf_domain_free(domain);
6943 if (msg_id != NULL)
6944 mailimf_msg_id_free(msg_id);
6945 err:
6946 return res;
6947}
6948#endif
6949
6950/*
6951optional-field = field-name ":" unstructured CRLF
6952*/
6953
6954static int
6955mailimf_optional_field_parse(const char * message, size_t length,
6956 size_t * index,
6957 struct mailimf_optional_field ** result)
6958{
6959 char * name;
6960 char * value;
6961 struct mailimf_optional_field * optional_field;
6962 size_t cur_token;
6963 int r;
6964 int res;
6965
6966 cur_token = * index;
6967
6968 r = mailimf_field_name_parse(message, length, &cur_token, &name);
6969 if (r != MAILIMF_NO_ERROR) {
6970 res = r;
6971 goto err;
6972 }
6973
6974 r = mailimf_colon_parse(message, length, &cur_token);
6975 if (r != MAILIMF_NO_ERROR) {
6976 res = r;
6977 goto free_name;
6978 }
6979
6980 r = mailimf_unstructured_parse(message, length, &cur_token, &value);
6981 if (r != MAILIMF_NO_ERROR) {
6982 res = r;
6983 goto free_name;
6984 }
6985
6986 r = mailimf_unstrict_crlf_parse(message, length, &cur_token);
6987 if (r != MAILIMF_NO_ERROR) {
6988 res = r;
6989 goto free_value;
6990 }
6991
6992 optional_field = mailimf_optional_field_new(name, value);
6993 if (optional_field == NULL) {
6994 res = MAILIMF_ERROR_MEMORY;
6995 goto free_value;
6996 }
6997
6998 * result = optional_field;
6999 * index = cur_token;
7000
7001 return MAILIMF_NO_ERROR;
7002
7003 free_value:
7004 mailimf_unstructured_free(value);
7005 free_name:
7006 mailimf_field_name_free(name);
7007 err:
7008 return res;
7009}
7010
7011/*
7012field-name = 1*ftext
7013*/
7014
7015static inline int is_ftext(char ch);
7016
7017static int mailimf_field_name_parse(const char * message, size_t length,
7018 size_t * index, char ** result)
7019{
7020 char * field_name;
7021 size_t cur_token;
7022 size_t end;
7023
7024 cur_token = * index;
7025
7026 end = cur_token;
7027 if (end >= length) {
7028 return MAILIMF_ERROR_PARSE;
7029 }
7030
7031 while (is_ftext(message[end])) {
7032 end ++;
7033 if (end >= length)
7034 break;
7035 }
7036 if (end == cur_token) {
7037 return MAILIMF_ERROR_PARSE;
7038 }
7039
7040 /* field_name = strndup(message + cur_token, end - cur_token); */
7041 field_name = malloc(end - cur_token + 1);
7042 if (field_name == NULL) {
7043 return MAILIMF_ERROR_MEMORY;
7044 }
7045 strncpy(field_name, message + cur_token, end - cur_token);
7046 field_name[end - cur_token] = '\0';
7047
7048 cur_token = end;
7049
7050 * index = cur_token;
7051 * result = field_name;
7052
7053 return MAILIMF_NO_ERROR;
7054}
7055
7056/*
7057ftext = %d33-57 / ; Any character except
7058 %d59-126 ; controls, SP, and
7059 ; ":".
7060*/
7061
7062static inline int is_ftext(char ch)
7063{
7064 unsigned char uch = (unsigned char) ch;
7065
7066 if (uch < 33)
7067 return FALSE;
7068
7069 if (uch == 58)
7070 return FALSE;
7071
7072 return TRUE;
7073}
7074
7075/*
7076static int mailimf_ftext_parse(const char * message, size_t length,
7077 size_t * index, gchar * result)
7078{
7079 return mailimf_typed_text_parse(message, length, index, result, is_ftext);
7080}
7081*/
7082
7083
7084
7085
7086static int mailimf_envelope_field_parse(const char * message, size_t length,
7087 size_t * index,
7088 struct mailimf_field ** result)
7089{
7090 size_t cur_token;
7091 int type;
7092 struct mailimf_orig_date * orig_date;
7093 struct mailimf_from * from;
7094 struct mailimf_sender * sender;
7095 struct mailimf_reply_to * reply_to;
7096 struct mailimf_to * to;
7097 struct mailimf_cc * cc;
7098 struct mailimf_bcc * bcc;
7099 struct mailimf_message_id * message_id;
7100 struct mailimf_in_reply_to * in_reply_to;
7101 struct mailimf_references * references;
7102 struct mailimf_subject * subject;
7103 struct mailimf_optional_field * optional_field;
7104 struct mailimf_field * field;
7105 int guessed_type;
7106 int r;
7107 int res;
7108
7109 cur_token = * index;
7110
7111 orig_date = NULL;
7112 from = NULL;
7113 sender = NULL;
7114 reply_to = NULL;
7115 to = NULL;
7116 cc = NULL;
7117 bcc = NULL;
7118 message_id = NULL;
7119 in_reply_to = NULL;
7120 references = NULL;
7121 subject = NULL;
7122 optional_field = NULL;
7123
7124 guessed_type = guess_header_type(message, length, cur_token);
7125 type = MAILIMF_FIELD_NONE;
7126
7127 switch (guessed_type) {
7128 case MAILIMF_FIELD_ORIG_DATE:
7129 r = mailimf_orig_date_parse(message, length, &cur_token,
7130 &orig_date);
7131 if (r == MAILIMF_NO_ERROR)
7132 type = guessed_type;
7133 else if (r == MAILIMF_ERROR_PARSE) {
7134 /* do nothing */
7135 }
7136 else {
7137 res = r;
7138 goto err;
7139 }
7140 break;
7141 case MAILIMF_FIELD_FROM:
7142 r = mailimf_from_parse(message, length, &cur_token,
7143 &from);
7144 if (r == MAILIMF_NO_ERROR)
7145 type = guessed_type;
7146 else if (r == MAILIMF_ERROR_PARSE) {
7147 /* do nothing */
7148 }
7149 else {
7150 res = r;
7151 goto err;
7152 }
7153 break;
7154 case MAILIMF_FIELD_SENDER:
7155 r = mailimf_sender_parse(message, length, &cur_token,
7156 &sender);
7157 if (r == MAILIMF_NO_ERROR)
7158 type = guessed_type;
7159 else if (r == MAILIMF_ERROR_PARSE) {
7160 /* do nothing */
7161 }
7162 else {
7163 res = r;
7164 goto err;
7165 }
7166 break;
7167 case MAILIMF_FIELD_REPLY_TO:
7168 r = mailimf_reply_to_parse(message, length, &cur_token,
7169 &reply_to);
7170 if (r == MAILIMF_NO_ERROR)
7171 type = guessed_type;
7172 else if (r == MAILIMF_ERROR_PARSE) {
7173 /* do nothing */
7174 }
7175 else {
7176 res = r;
7177 goto err;
7178 }
7179 break;
7180 case MAILIMF_FIELD_TO:
7181 r = mailimf_to_parse(message, length, &cur_token,
7182 &to);
7183 if (r == MAILIMF_NO_ERROR)
7184 type = guessed_type;
7185 else if (r == MAILIMF_ERROR_PARSE) {
7186 /* do nothing */
7187 }
7188 else {
7189 res = r;
7190 goto err;
7191 }
7192 break;
7193 case MAILIMF_FIELD_CC:
7194 r = mailimf_cc_parse(message, length, &cur_token,
7195 &cc);
7196 if (r == MAILIMF_NO_ERROR)
7197 type = guessed_type;
7198 else if (r == MAILIMF_ERROR_PARSE) {
7199 /* do nothing */
7200 }
7201 else {
7202 res = r;
7203 goto err;
7204 }
7205 break;
7206 case MAILIMF_FIELD_BCC:
7207 r = mailimf_bcc_parse(message, length, &cur_token,
7208 &bcc);
7209 if (r == MAILIMF_NO_ERROR)
7210 type = guessed_type;
7211 else if (r == MAILIMF_ERROR_PARSE) {
7212 /* do nothing */
7213 }
7214 else {
7215 res = r;
7216 goto err;
7217 }
7218 break;
7219 case MAILIMF_FIELD_MESSAGE_ID:
7220 r = mailimf_message_id_parse(message, length, &cur_token,
7221 &message_id);
7222 if (r == MAILIMF_NO_ERROR)
7223 type = guessed_type;
7224 else if (r == MAILIMF_ERROR_PARSE) {
7225 /* do nothing */
7226 }
7227 else {
7228 res = r;
7229 goto err;
7230 }
7231 break;
7232 case MAILIMF_FIELD_IN_REPLY_TO:
7233 r = mailimf_in_reply_to_parse(message, length, &cur_token,
7234 &in_reply_to);
7235 if (r == MAILIMF_NO_ERROR)
7236 type = guessed_type;
7237 else if (r == MAILIMF_ERROR_PARSE) {
7238 /* do nothing */
7239 }
7240 else {
7241 res = r;
7242 goto err;
7243 }
7244 break;
7245 case MAILIMF_FIELD_REFERENCES:
7246 r = mailimf_references_parse(message, length, &cur_token,
7247 &references);
7248 if (r == MAILIMF_NO_ERROR)
7249 type = guessed_type;
7250 else if (r == MAILIMF_ERROR_PARSE) {
7251 /* do nothing */
7252 }
7253 else {
7254 res = r;
7255 goto err;
7256 }
7257 break;
7258 case MAILIMF_FIELD_SUBJECT:
7259 r = mailimf_subject_parse(message, length, &cur_token,
7260 &subject);
7261 if (r == MAILIMF_NO_ERROR)
7262 type = guessed_type;
7263 else if (r == MAILIMF_ERROR_PARSE) {
7264 /* do nothing */
7265 }
7266 else {
7267 res = r;
7268 goto err;
7269 }
7270 break;
7271 }
7272
7273 if (type == MAILIMF_FIELD_NONE) {
7274 res = MAILIMF_ERROR_PARSE;
7275 goto err;
7276 }
7277
7278 field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
7279 NULL, NULL, NULL,
7280 orig_date, from, sender, reply_to, to,
7281 cc, bcc, message_id, in_reply_to, references,
7282 subject, NULL, NULL, optional_field);
7283 if (field == NULL) {
7284 res = MAILIMF_ERROR_MEMORY;
7285 goto free_field;
7286 }
7287
7288 * result = field;
7289 * index = cur_token;
7290
7291 return MAILIMF_NO_ERROR;
7292
7293 free_field:
7294 if (orig_date != NULL)
7295 mailimf_orig_date_free(orig_date);
7296 if (from != NULL)
7297 mailimf_from_free(from);
7298 if (sender != NULL)
7299 mailimf_sender_free(sender);
7300 if (reply_to != NULL)
7301 mailimf_reply_to_free(reply_to);
7302 if (to != NULL)
7303 mailimf_to_free(to);
7304 if (cc != NULL)
7305 mailimf_cc_free(cc);
7306 if (bcc != NULL)
7307 mailimf_bcc_free(bcc);
7308 if (message_id != NULL)
7309 mailimf_message_id_free(message_id);
7310 if (in_reply_to != NULL)
7311 mailimf_in_reply_to_free(in_reply_to);
7312 if (references != NULL)
7313 mailimf_references_free(references);
7314 if (subject != NULL)
7315 mailimf_subject_free(subject);
7316 if (optional_field != NULL)
7317 mailimf_optional_field_free(optional_field);
7318 err:
7319 return res;
7320}
7321
7322int mailimf_envelope_fields_parse(const char * message, size_t length,
7323 size_t * index,
7324 struct mailimf_fields ** result)
7325{
7326 size_t cur_token;
7327 clist * list;
7328 struct mailimf_fields * fields;
7329 int r;
7330 int res;
7331
7332 cur_token = * index;
7333
7334 list = clist_new();
7335 if (list == NULL) {
7336 res = MAILIMF_ERROR_MEMORY;
7337 goto err;
7338 }
7339
7340 while (1) {
7341 struct mailimf_field * elt;
7342
7343 r = mailimf_envelope_field_parse(message, length, &cur_token, &elt);
7344 if (r == MAILIMF_NO_ERROR) {
7345 r = clist_append(list, elt);
7346 if (r < 0) {
7347 res = MAILIMF_ERROR_MEMORY;
7348 goto free;
7349 }
7350 }
7351 else if (r == MAILIMF_ERROR_PARSE) {
7352 r = mailimf_ignore_field_parse(message, length, &cur_token);
7353 if (r == MAILIMF_NO_ERROR) {
7354 /* do nothing */
7355 }
7356 else if (r == MAILIMF_ERROR_PARSE) {
7357 break;
7358 }
7359 else {
7360 res = r;
7361 goto free;
7362 }
7363 }
7364 else {
7365 res = r;
7366 goto free;
7367 }
7368 }
7369
7370 fields = mailimf_fields_new(list);
7371 if (fields == NULL) {
7372 res = MAILIMF_ERROR_MEMORY;
7373 goto free;
7374 }
7375
7376 * result = fields;
7377 * index = cur_token;
7378
7379 return MAILIMF_NO_ERROR;
7380
7381 free:
7382 if (list != NULL) {
7383 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7384 clist_free(list);
7385 }
7386 err:
7387 return res;
7388}
7389
7390
7391static int
7392mailimf_envelope_or_optional_field_parse(const char * message,
7393 size_t length,
7394 size_t * index,
7395 struct mailimf_field ** result)
7396{
7397 int r;
7398 size_t cur_token;
7399 struct mailimf_optional_field * optional_field;
7400 struct mailimf_field * field;
7401
7402 r = mailimf_envelope_field_parse(message, length, index, result);
7403 if (r == MAILIMF_NO_ERROR)
7404 return MAILIMF_NO_ERROR;
7405
7406 cur_token = * index;
7407
7408 r = mailimf_optional_field_parse(message, length, &cur_token,
7409 &optional_field);
7410 if (r != MAILIMF_NO_ERROR)
7411 return r;
7412
7413 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL,
7414 NULL, NULL, NULL,
7415 NULL, NULL, NULL,
7416 NULL, NULL, NULL,
7417 NULL, NULL, NULL,
7418 NULL, NULL, NULL, NULL, NULL,
7419 NULL, NULL, NULL, optional_field);
7420 if (field == NULL) {
7421 mailimf_optional_field_free(optional_field);
7422 return MAILIMF_ERROR_MEMORY;
7423 }
7424
7425 * result = field;
7426 * index = cur_token;
7427
7428 return MAILIMF_NO_ERROR;
7429}
7430
7431
7432int
7433mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
7434 size_t * index,
7435 struct mailimf_fields ** result)
7436{
7437 size_t cur_token;
7438 clist * list;
7439 struct mailimf_fields * fields;
7440 int r;
7441 int res;
7442
7443 cur_token = * index;
7444
7445 list = NULL;
7446
7447 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7448 &list,
7449 (mailimf_struct_parser *)
7450 mailimf_envelope_or_optional_field_parse,
7451 (mailimf_struct_destructor *)
7452 mailimf_field_free);
7453 switch (r) {
7454 case MAILIMF_NO_ERROR:
7455 /* do nothing */
7456 break;
7457
7458 case MAILIMF_ERROR_PARSE:
7459 list = clist_new();
7460 if (list == NULL) {
7461 res = MAILIMF_ERROR_MEMORY;
7462 goto err;
7463 }
7464 break;
7465
7466 default:
7467 res = r;
7468 goto err;
7469 }
7470
7471 fields = mailimf_fields_new(list);
7472 if (fields == NULL) {
7473 res = MAILIMF_ERROR_MEMORY;
7474 goto free;
7475 }
7476
7477 * result = fields;
7478 * index = cur_token;
7479
7480 return MAILIMF_NO_ERROR;
7481
7482 free:
7483 if (list != NULL) {
7484 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7485 clist_free(list);
7486 }
7487 err:
7488 return res;
7489}
7490
7491
7492
7493static int
7494mailimf_only_optional_field_parse(const char * message,
7495 size_t length,
7496 size_t * index,
7497 struct mailimf_field ** result)
7498{
7499 int r;
7500 size_t cur_token;
7501 struct mailimf_optional_field * optional_field;
7502 struct mailimf_field * field;
7503
7504 cur_token = * index;
7505
7506 r = mailimf_optional_field_parse(message, length, &cur_token,
7507 &optional_field);
7508 if (r != MAILIMF_NO_ERROR)
7509 return r;
7510
7511 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL,
7512 NULL, NULL, NULL, NULL, NULL,
7513 NULL, NULL, NULL, NULL, NULL,
7514 NULL, NULL, NULL, NULL, NULL,
7515 NULL, NULL, NULL, optional_field);
7516 if (field == NULL) {
7517 mailimf_optional_field_free(optional_field);
7518 return MAILIMF_ERROR_MEMORY;
7519 }
7520
7521 * result = field;
7522 * index = cur_token;
7523
7524 return MAILIMF_NO_ERROR;
7525}
7526
7527
7528int
7529mailimf_optional_fields_parse(const char * message, size_t length,
7530 size_t * index,
7531 struct mailimf_fields ** result)
7532{
7533 size_t cur_token;
7534 clist * list;
7535 struct mailimf_fields * fields;
7536 int r;
7537 int res;
7538
7539 cur_token = * index;
7540
7541 list = NULL;
7542
7543 r = mailimf_struct_multiple_parse(message, length, &cur_token,
7544 &list,
7545 (mailimf_struct_parser *)
7546 mailimf_only_optional_field_parse,
7547 (mailimf_struct_destructor *)
7548 mailimf_field_free);
7549 switch (r) {
7550 case MAILIMF_NO_ERROR:
7551 /* do nothing */
7552 break;
7553
7554 case MAILIMF_ERROR_PARSE:
7555 list = clist_new();
7556 if (list == NULL) {
7557 res = MAILIMF_ERROR_MEMORY;
7558 goto err;
7559 }
7560 break;
7561
7562 default:
7563 res = r;
7564 goto err;
7565 }
7566
7567 fields = mailimf_fields_new(list);
7568 if (fields == NULL) {
7569 res = MAILIMF_ERROR_MEMORY;
7570 goto free;
7571 }
7572
7573 * result = fields;
7574 * index = cur_token;
7575
7576 return MAILIMF_NO_ERROR;
7577
7578 free:
7579 if (list != NULL) {
7580 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
7581 clist_free(list);
7582 }
7583 err:
7584 return res;
7585}
diff --git a/libetpan/src/low-level/imf/mailimf.h b/libetpan/src/low-level/imf/mailimf.h
new file mode 100644
index 0000000..c2231dd
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf.h
@@ -0,0 +1,347 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_H
37
38#define MAILIMF_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45#include <libetpan/mailimf_write_generic.h>
46#include <libetpan/mailimf_write_file.h>
47#include <libetpan/mailimf_write_mem.h>
48#include <libetpan/mailimf_types_helper.h>
49
50#include <inttypes.h>
51#include <sys/types.h>
52
53/*
54 mailimf_message_parse will parse the given message
55
56 @param message this is a string containing the message content
57 @param length this is the size of the given string
58 @param index this is a pointer to the start of the message in
59 the given string, (* index) is modified to point at the end
60 of the parsed data
61 @param result the result of the parse operation is stored in
62 (* result)
63
64 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
65*/
66
67int mailimf_message_parse(const char * message, size_t length,
68 size_t * index,
69 struct mailimf_message ** result);
70
71/*
72 mailimf_body_parse will parse the given text part of a message
73
74 @param message this is a string containing the message text part
75 @param length this is the size of the given string
76 @param index this is a pointer to the start of the message text part in
77 the given string, (* index) is modified to point at the end
78 of the parsed data
79 @param result the result of the parse operation is stored in
80 (* result)
81
82 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
83*/
84
85int mailimf_body_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailimf_body ** result);
88
89/*
90 mailimf_fields_parse will parse the given header fields
91
92 @param message this is a string containing the header fields
93 @param length this is the size of the given string
94 @param index this is a pointer to the start of the header fields in
95 the given string, (* index) is modified to point at the end
96 of the parsed data
97 @param result the result of the parse operation is stored in
98 (* result)
99
100 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
101*/
102
103int mailimf_fields_parse(const char * message, size_t length,
104 size_t * index,
105 struct mailimf_fields ** result);
106
107/*
108 mailimf_mailbox_list_parse will parse the given mailbox list
109
110 @param message this is a string containing the mailbox list
111 @param length this is the size of the given string
112 @param index this is a pointer to the start of the mailbox list in
113 the given string, (* index) is modified to point at the end
114 of the parsed data
115 @param result the result of the parse operation is stored in
116 (* result)
117
118 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
119*/
120
121int
122mailimf_mailbox_list_parse(const char * message, size_t length,
123 size_t * index,
124 struct mailimf_mailbox_list ** result);
125
126/*
127 mailimf_address_list_parse will parse the given address list
128
129 @param message this is a string containing the address list
130 @param length this is the size of the given string
131 @param index this is a pointer to the start of the address list in
132 the given string, (* index) is modified to point at the end
133 of the parsed data
134 @param result the result of the parse operation is stored in
135 (* result)
136
137 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
138*/
139
140int
141mailimf_address_list_parse(const char * message, size_t length,
142 size_t * index,
143 struct mailimf_address_list ** result);
144
145/*
146 mailimf_address_parse will parse the given address
147
148 @param message this is a string containing the address
149 @param length this is the size of the given string
150 @param index this is a pointer to the start of the address in
151 the given string, (* index) is modified to point at the end
152 of the parsed data
153 @param result the result of the parse operation is stored in
154 (* result)
155
156 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
157*/
158
159int mailimf_address_parse(const char * message, size_t length,
160 size_t * index,
161 struct mailimf_address ** result);
162
163/*
164 mailimf_mailbox_parse will parse the given address
165
166 @param message this is a string containing the mailbox
167 @param length this is the size of the given string
168 @param index this is a pointer to the start of the mailbox in
169 the given string, (* index) is modified to point at the end
170 of the parsed data
171 @param result the result of the parse operation is stored in
172 (* result)
173
174 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
175*/
176
177int mailimf_mailbox_parse(const char * message, size_t length,
178 size_t * index,
179 struct mailimf_mailbox ** result);
180
181/*
182 mailimf_date_time_parse will parse the given RFC 2822 date
183
184 @param message this is a string containing the date
185 @param length this is the size of the given string
186 @param index this is a pointer to the start of the date in
187 the given string, (* index) is modified to point at the end
188 of the parsed data
189 @param result the result of the parse operation is stored in
190 (* result)
191
192 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
193*/
194
195int mailimf_date_time_parse(const char * message, size_t length,
196 size_t * index,
197 struct mailimf_date_time ** result);
198
199/*
200 mailimf_envelope_fields_parse will parse the given fields (Date,
201 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
202 References and Subject)
203
204 @param message this is a string containing the header fields
205 @param length this is the size of the given string
206 @param index this is a pointer to the start of the header fields in
207 the given string, (* index) is modified to point at the end
208 of the parsed data
209 @param result the result of the parse operation is stored in
210 (* result)
211
212 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
213*/
214
215int mailimf_envelope_fields_parse(const char * message, size_t length,
216 size_t * index,
217 struct mailimf_fields ** result);
218
219/*
220 mailimf_ignore_field_parse will skip the given field
221
222 @param message this is a string containing the header field
223 @param length this is the size of the given string
224 @param index this is a pointer to the start of the header field in
225 the given string, (* index) is modified to point at the end
226 of the parsed data
227
228 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
229*/
230
231
232int mailimf_ignore_field_parse(const char * message, size_t length,
233 size_t * index);
234
235/*
236 mailimf_envelope_fields will parse the given fields (Date,
237 From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
238 References and Subject), other fields will be added as optional
239 fields.
240
241 @param message this is a string containing the header fields
242 @param length this is the size of the given string
243 @param index this is a pointer to the start of the header fields in
244 the given string, (* index) is modified to point at the end
245 of the parsed data
246 @param result the result of the parse operation is stored in
247 (* result)
248
249 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
250*/
251
252
253int
254mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
255 size_t * index,
256 struct mailimf_fields ** result);
257
258/*
259 mailimf_envelope_fields will parse the given fields as optional
260 fields.
261
262 @param message this is a string containing the header fields
263 @param length this is the size of the given string
264 @param index this is a pointer to the start of the header fields in
265 the given string, (* index) is modified to point at the end
266 of the parsed data
267 @param result the result of the parse operation is stored in
268 (* result)
269
270 @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
271*/
272
273int
274mailimf_optional_fields_parse(const char * message, size_t length,
275 size_t * index,
276 struct mailimf_fields ** result);
277
278
279/* internal use, exported for MIME */
280
281int mailimf_fws_parse(const char * message, size_t length, size_t * index);
282
283int mailimf_cfws_parse(const char * message, size_t length,
284 size_t * index);
285
286int mailimf_char_parse(const char * message, size_t length,
287 size_t * index, char token);
288
289int mailimf_unstrict_char_parse(const char * message, size_t length,
290 size_t * index, char token);
291
292int mailimf_crlf_parse(const char * message, size_t length, size_t * index);
293
294int
295mailimf_custom_string_parse(const char * message, size_t length,
296 size_t * index, char ** result,
297 int (* is_custom_char)(char));
298
299int
300mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
301 size_t * index, char * token,
302 size_t token_length);
303
304#define mailimf_token_case_insensitive_parse(message, length, index, token) \
305 mailimf_token_case_insensitive_len_parse(message, length, index, token, \
306 sizeof(token) - 1)
307
308int mailimf_quoted_string_parse(const char * message, size_t length,
309 size_t * index, char ** result);
310
311int
312mailimf_number_parse(const char * message, size_t length,
313 size_t * index, uint32_t * result);
314
315int mailimf_msg_id_parse(const char * message, size_t length,
316 size_t * index,
317 char ** result);
318
319int mailimf_msg_id_list_parse(const char * message, size_t length,
320 size_t * index, clist ** result);
321
322int mailimf_word_parse(const char * message, size_t length,
323 size_t * index, char ** result);
324
325int mailimf_atom_parse(const char * message, size_t length,
326 size_t * index, char ** result);
327
328int mailimf_fws_atom_parse(const char * message, size_t length,
329 size_t * index, char ** result);
330
331int mailimf_fws_word_parse(const char * message, size_t length,
332 size_t * index, char ** result);
333
334int mailimf_fws_quoted_string_parse(const char * message, size_t length,
335 size_t * index, char ** result);
336
337/* exported for IMAP */
338
339int mailimf_references_parse(const char * message, size_t length,
340 size_t * index,
341 struct mailimf_references ** result);
342
343#ifdef __cplusplus
344}
345#endif
346
347#endif
diff --git a/libetpan/src/low-level/imf/mailimf_types.c b/libetpan/src/low-level/imf/mailimf_types.c
new file mode 100644
index 0000000..a6e4db9
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types.c
@@ -0,0 +1,868 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf_types.h"
37#include "mmapstring.h"
38#include <stdlib.h>
39
40void mailimf_atom_free(char * atom)
41{
42 free(atom);
43}
44
45void mailimf_dot_atom_free(char * dot_atom)
46{
47 free(dot_atom);
48}
49
50void mailimf_dot_atom_text_free(char * dot_atom)
51{
52 free(dot_atom);
53}
54
55void mailimf_quoted_string_free(char * quoted_string)
56{
57 free(quoted_string);
58}
59
60void mailimf_word_free(char * word)
61{
62 free(word);
63}
64
65void mailimf_phrase_free(char * phrase)
66{
67 free(phrase);
68}
69
70void mailimf_unstructured_free(char * unstructured)
71{
72 free(unstructured);
73}
74
75
76struct mailimf_date_time *
77mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
78 int dt_hour, int dt_min, int dt_sec, int dt_zone)
79{
80 struct mailimf_date_time * date_time;
81
82 date_time = malloc(sizeof(* date_time));
83 if (date_time == NULL)
84 return NULL;
85
86 date_time->dt_day = dt_day;
87 date_time->dt_month = dt_month;
88 date_time->dt_year = dt_year;
89 date_time->dt_hour = dt_hour;
90 date_time->dt_min = dt_min;
91 date_time->dt_sec = dt_sec;
92 date_time->dt_zone = dt_zone;
93
94 return date_time;
95}
96
97
98void mailimf_date_time_free(struct mailimf_date_time * date_time)
99{
100 free(date_time);
101}
102
103
104
105
106struct mailimf_address *
107mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
108 struct mailimf_group * ad_group)
109{
110 struct mailimf_address * address;
111
112 address = malloc(sizeof(* address));
113 if (address == NULL)
114 return NULL;
115
116 address->ad_type = ad_type;
117 switch (ad_type) {
118 case MAILIMF_ADDRESS_MAILBOX:
119 address->ad_data.ad_mailbox = ad_mailbox;
120 break;
121 case MAILIMF_ADDRESS_GROUP:
122 address->ad_data.ad_group = ad_group;
123 break;
124 }
125
126 return address;
127}
128
129void mailimf_address_free(struct mailimf_address * address)
130{
131 switch (address->ad_type) {
132 case MAILIMF_ADDRESS_MAILBOX:
133 mailimf_mailbox_free(address->ad_data.ad_mailbox);
134 break;
135 case MAILIMF_ADDRESS_GROUP:
136 mailimf_group_free(address->ad_data.ad_group);
137 }
138 free(address);
139}
140
141struct mailimf_mailbox *
142mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec)
143{
144 struct mailimf_mailbox * mb;
145
146 mb = malloc(sizeof(* mb));
147 if (mb == NULL)
148 return NULL;
149
150 mb->mb_display_name = mb_display_name;
151 mb->mb_addr_spec = mb_addr_spec;
152
153 return mb;
154}
155
156void mailimf_mailbox_free(struct mailimf_mailbox * mailbox)
157{
158 if (mailbox->mb_display_name != NULL)
159 mailimf_display_name_free(mailbox->mb_display_name);
160 mailimf_addr_spec_free(mailbox->mb_addr_spec);
161 free(mailbox);
162}
163
164
165void mailimf_angle_addr_free(char * angle_addr)
166{
167 free(angle_addr);
168}
169
170
171struct mailimf_group *
172mailimf_group_new(char * grp_display_name,
173 struct mailimf_mailbox_list * grp_mb_list)
174{
175 struct mailimf_group * group;
176
177 group = malloc(sizeof(* group));
178 if (group == NULL)
179 return NULL;
180
181 group->grp_display_name = grp_display_name;
182 group->grp_mb_list = grp_mb_list;
183
184 return group;
185}
186
187void mailimf_group_free(struct mailimf_group * group)
188{
189 if (group->grp_mb_list)
190 mailimf_mailbox_list_free(group->grp_mb_list);
191 mailimf_display_name_free(group->grp_display_name);
192 free(group);
193}
194
195void mailimf_display_name_free(char * display_name)
196{
197 mailimf_phrase_free(display_name);
198}
199
200
201struct mailimf_mailbox_list *
202mailimf_mailbox_list_new(clist * mb_list)
203{
204 struct mailimf_mailbox_list * mbl;
205
206 mbl = malloc(sizeof(* mbl));
207 if (mbl == NULL)
208 return NULL;
209
210 mbl->mb_list = mb_list;
211
212 return mbl;
213}
214
215void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list)
216{
217 clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL);
218 clist_free(mb_list->mb_list);
219 free(mb_list);
220}
221
222
223
224struct mailimf_address_list *
225mailimf_address_list_new(clist * ad_list)
226{
227 struct mailimf_address_list * addr_list;
228
229 addr_list = malloc(sizeof(* addr_list));
230 if (addr_list == NULL)
231 return NULL;
232
233 addr_list->ad_list = ad_list;
234
235 return addr_list;
236}
237
238void mailimf_address_list_free(struct mailimf_address_list * addr_list)
239{
240 clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL);
241 clist_free(addr_list->ad_list);
242 free(addr_list);
243}
244
245
246void mailimf_addr_spec_free(char * addr_spec)
247{
248 free(addr_spec);
249}
250
251void mailimf_local_part_free(char * local_part)
252{
253 free(local_part);
254}
255
256void mailimf_domain_free(char * domain)
257{
258 free(domain);
259}
260
261void mailimf_domain_literal_free(char * domain_literal)
262{
263 free(domain_literal);
264}
265
266
267
268struct mailimf_message *
269mailimf_message_new(struct mailimf_fields * msg_fields,
270 struct mailimf_body * msg_body)
271{
272 struct mailimf_message * message;
273
274 message = malloc(sizeof(* message));
275 if (message == NULL)
276 return NULL;
277
278 message->msg_fields = msg_fields;
279 message->msg_body = msg_body;
280
281 return message;
282}
283
284void mailimf_message_free(struct mailimf_message * message)
285{
286 mailimf_body_free(message->msg_body);
287 mailimf_fields_free(message->msg_fields);
288 free(message);
289}
290
291
292struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size)
293{
294 struct mailimf_body * body;
295
296 body = malloc(sizeof(* body));
297 if (body == NULL)
298 return NULL;
299 body->bd_text = bd_text;
300 body->bd_size = bd_size;
301
302 return body;
303}
304
305void mailimf_body_free(struct mailimf_body * body)
306{
307 free(body);
308}
309
310
311
312struct mailimf_field *
313mailimf_field_new(int fld_type,
314 struct mailimf_return * fld_return_path,
315 struct mailimf_orig_date * fld_resent_date,
316 struct mailimf_from * fld_resent_from,
317 struct mailimf_sender * fld_resent_sender,
318 struct mailimf_to * fld_resent_to,
319 struct mailimf_cc * fld_resent_cc,
320 struct mailimf_bcc * fld_resent_bcc,
321 struct mailimf_message_id * fld_resent_msg_id,
322 struct mailimf_orig_date * fld_orig_date,
323 struct mailimf_from * fld_from,
324 struct mailimf_sender * fld_sender,
325 struct mailimf_reply_to * fld_reply_to,
326 struct mailimf_to * fld_to,
327 struct mailimf_cc * fld_cc,
328 struct mailimf_bcc * fld_bcc,
329 struct mailimf_message_id * fld_message_id,
330 struct mailimf_in_reply_to * fld_in_reply_to,
331 struct mailimf_references * fld_references,
332 struct mailimf_subject * fld_subject,
333 struct mailimf_comments * fld_comments,
334 struct mailimf_keywords * fld_keywords,
335 struct mailimf_optional_field * fld_optional_field)
336{
337 struct mailimf_field * field;
338
339 field = malloc(sizeof(* field));
340 if (field == NULL)
341 return NULL;
342
343 field->fld_type = fld_type;
344 switch (fld_type) {
345 case MAILIMF_FIELD_RETURN_PATH:
346 field->fld_data.fld_return_path = fld_return_path;
347 break;
348 case MAILIMF_FIELD_RESENT_DATE:
349 field->fld_data.fld_resent_date = fld_resent_date;
350 break;
351 case MAILIMF_FIELD_RESENT_FROM:
352 field->fld_data.fld_resent_from = fld_resent_from;
353 break;
354 case MAILIMF_FIELD_RESENT_SENDER:
355 field->fld_data.fld_resent_sender = fld_resent_sender;
356 break;
357 case MAILIMF_FIELD_RESENT_TO:
358 field->fld_data.fld_resent_to = fld_resent_to;
359 break;
360 case MAILIMF_FIELD_RESENT_CC:
361 field->fld_data.fld_resent_cc = fld_resent_cc;
362 break;
363 case MAILIMF_FIELD_RESENT_BCC:
364 field->fld_data.fld_resent_bcc = fld_resent_bcc;
365 break;
366 case MAILIMF_FIELD_RESENT_MSG_ID:
367 field->fld_data.fld_resent_msg_id = fld_resent_msg_id;
368 break;
369 case MAILIMF_FIELD_ORIG_DATE:
370 field->fld_data.fld_orig_date = fld_orig_date;
371 break;
372 case MAILIMF_FIELD_FROM:
373 field->fld_data.fld_from = fld_from;
374 break;
375 case MAILIMF_FIELD_SENDER:
376 field->fld_data.fld_sender = fld_sender;
377 break;
378 case MAILIMF_FIELD_REPLY_TO:
379 field->fld_data.fld_reply_to = fld_reply_to;
380 break;
381 case MAILIMF_FIELD_TO:
382 field->fld_data.fld_to = fld_to;
383 break;
384 case MAILIMF_FIELD_CC:
385 field->fld_data.fld_cc = fld_cc;
386 break;
387 case MAILIMF_FIELD_BCC:
388 field->fld_data.fld_bcc = fld_bcc;
389 break;
390 case MAILIMF_FIELD_MESSAGE_ID:
391 field->fld_data.fld_message_id = fld_message_id;
392 break;
393 case MAILIMF_FIELD_IN_REPLY_TO:
394 field->fld_data.fld_in_reply_to = fld_in_reply_to;
395 break;
396 case MAILIMF_FIELD_REFERENCES:
397 field->fld_data.fld_references = fld_references;
398 break;
399 case MAILIMF_FIELD_SUBJECT:
400 field->fld_data.fld_subject = fld_subject;
401 break;
402 case MAILIMF_FIELD_COMMENTS:
403 field->fld_data.fld_comments = fld_comments;
404 break;
405 case MAILIMF_FIELD_KEYWORDS:
406 field->fld_data.fld_keywords = fld_keywords;
407 break;
408 case MAILIMF_FIELD_OPTIONAL_FIELD:
409 field->fld_data.fld_optional_field = fld_optional_field;
410 break;
411 }
412
413 return field;
414}
415
416void mailimf_field_free(struct mailimf_field * field)
417{
418 switch (field->fld_type) {
419 case MAILIMF_FIELD_RETURN_PATH:
420 mailimf_return_free(field->fld_data.fld_return_path);
421 break;
422 case MAILIMF_FIELD_RESENT_DATE:
423 mailimf_orig_date_free(field->fld_data.fld_resent_date);
424 break;
425 case MAILIMF_FIELD_RESENT_FROM:
426 mailimf_from_free(field->fld_data.fld_resent_from);
427 break;
428 case MAILIMF_FIELD_RESENT_SENDER:
429 mailimf_sender_free(field->fld_data.fld_resent_sender);
430 break;
431 case MAILIMF_FIELD_RESENT_TO:
432 mailimf_to_free(field->fld_data.fld_resent_to);
433 break;
434 case MAILIMF_FIELD_RESENT_CC:
435 mailimf_cc_free(field->fld_data.fld_resent_cc);
436 break;
437 case MAILIMF_FIELD_RESENT_BCC:
438 mailimf_bcc_free(field->fld_data.fld_resent_bcc);
439 break;
440 case MAILIMF_FIELD_RESENT_MSG_ID:
441 mailimf_message_id_free(field->fld_data.fld_resent_msg_id);
442 break;
443 case MAILIMF_FIELD_ORIG_DATE:
444 mailimf_orig_date_free(field->fld_data.fld_orig_date);
445 break;
446 case MAILIMF_FIELD_FROM:
447 mailimf_from_free(field->fld_data.fld_from);
448 break;
449 case MAILIMF_FIELD_SENDER:
450 mailimf_sender_free(field->fld_data.fld_sender);
451 break;
452 case MAILIMF_FIELD_REPLY_TO:
453 mailimf_reply_to_free(field->fld_data.fld_reply_to);
454 break;
455 case MAILIMF_FIELD_TO:
456 mailimf_to_free(field->fld_data.fld_to);
457 break;
458 case MAILIMF_FIELD_CC:
459 mailimf_cc_free(field->fld_data.fld_cc);
460 break;
461 case MAILIMF_FIELD_BCC:
462 mailimf_bcc_free(field->fld_data.fld_bcc);
463 break;
464 case MAILIMF_FIELD_MESSAGE_ID:
465 mailimf_message_id_free(field->fld_data.fld_message_id);
466 break;
467 case MAILIMF_FIELD_IN_REPLY_TO:
468 mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to);
469 break;
470 case MAILIMF_FIELD_REFERENCES:
471 mailimf_references_free(field->fld_data.fld_references);
472 break;
473 case MAILIMF_FIELD_SUBJECT:
474 mailimf_subject_free(field->fld_data.fld_subject);
475 break;
476 case MAILIMF_FIELD_COMMENTS:
477 mailimf_comments_free(field->fld_data.fld_comments);
478 break;
479 case MAILIMF_FIELD_KEYWORDS:
480 mailimf_keywords_free(field->fld_data.fld_keywords);
481 break;
482 case MAILIMF_FIELD_OPTIONAL_FIELD:
483 mailimf_optional_field_free(field->fld_data.fld_optional_field);
484 break;
485 }
486
487 free(field);
488}
489
490struct mailimf_fields * mailimf_fields_new(clist * fld_list)
491{
492 struct mailimf_fields * fields;
493
494 fields = malloc(sizeof(* fields));
495 if (fields == NULL)
496 return NULL;
497
498 fields->fld_list = fld_list;
499
500 return fields;
501}
502
503void mailimf_fields_free(struct mailimf_fields * fields)
504{
505 if (fields->fld_list != NULL) {
506 clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL);
507 clist_free(fields->fld_list);
508 }
509 free(fields);
510}
511
512
513struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
514 dt_date_time)
515{
516 struct mailimf_orig_date * orig_date;
517
518 orig_date = malloc(sizeof(* orig_date));
519 if (orig_date == NULL)
520 return NULL;
521
522 orig_date->dt_date_time = dt_date_time;
523
524 return orig_date;
525}
526
527void mailimf_orig_date_free(struct mailimf_orig_date * orig_date)
528{
529 if (orig_date->dt_date_time != NULL)
530 mailimf_date_time_free(orig_date->dt_date_time);
531 free(orig_date);
532}
533
534struct mailimf_from *
535mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list)
536{
537 struct mailimf_from * from;
538
539 from = malloc(sizeof(* from));
540 if (from == NULL)
541 return NULL;
542
543 from->frm_mb_list = frm_mb_list;
544
545 return from;
546}
547
548void mailimf_from_free(struct mailimf_from * from)
549{
550 if (from->frm_mb_list != NULL)
551 mailimf_mailbox_list_free(from->frm_mb_list);
552 free(from);
553}
554
555struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb)
556{
557 struct mailimf_sender * sender;
558
559 sender = malloc(sizeof(* sender));
560 if (sender == NULL)
561 return NULL;
562
563 sender->snd_mb = snd_mb;
564
565 return sender;
566}
567
568void mailimf_sender_free(struct mailimf_sender * sender)
569{
570 if (sender->snd_mb != NULL)
571 mailimf_mailbox_free(sender->snd_mb);
572 free(sender);
573}
574
575struct mailimf_reply_to *
576mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list)
577{
578 struct mailimf_reply_to * reply_to;
579
580 reply_to = malloc(sizeof(* reply_to));
581 if (reply_to == NULL)
582 return NULL;
583
584 reply_to->rt_addr_list = rt_addr_list;
585
586 return reply_to;
587}
588
589void mailimf_reply_to_free(struct mailimf_reply_to * reply_to)
590{
591 if (reply_to->rt_addr_list != NULL)
592 mailimf_address_list_free(reply_to->rt_addr_list);
593 free(reply_to);
594}
595
596struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list)
597{
598 struct mailimf_to * to;
599
600 to = malloc(sizeof(* to));
601 if (to == NULL)
602 return NULL;
603
604 to->to_addr_list = to_addr_list;
605
606 return to;
607}
608
609void mailimf_to_free(struct mailimf_to * to)
610{
611 if (to->to_addr_list != NULL)
612 mailimf_address_list_free(to->to_addr_list);
613 free(to);
614}
615
616struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list)
617{
618 struct mailimf_cc * cc;
619
620 cc = malloc(sizeof(* cc));
621 if (cc == NULL)
622 return NULL;
623
624 cc->cc_addr_list = cc_addr_list;
625
626 return cc;
627}
628
629void mailimf_cc_free(struct mailimf_cc * cc)
630{
631 if (cc->cc_addr_list != NULL)
632 mailimf_address_list_free(cc->cc_addr_list);
633 free(cc);
634}
635
636struct mailimf_bcc *
637mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list)
638{
639 struct mailimf_bcc * bcc;
640
641 bcc = malloc(sizeof(* bcc));
642 if (bcc == NULL)
643 return NULL;
644
645 bcc->bcc_addr_list = bcc_addr_list;
646
647 return bcc;
648}
649
650void mailimf_bcc_free(struct mailimf_bcc * bcc)
651{
652 if (bcc->bcc_addr_list != NULL)
653 mailimf_address_list_free(bcc->bcc_addr_list);
654 free(bcc);
655}
656
657struct mailimf_message_id * mailimf_message_id_new(char * mid_value)
658{
659 struct mailimf_message_id * message_id;
660
661 message_id = malloc(sizeof(* message_id));
662 if (message_id == NULL)
663 return NULL;
664
665 message_id->mid_value = mid_value;
666
667 return message_id;
668}
669
670void mailimf_message_id_free(struct mailimf_message_id * message_id)
671{
672 if (message_id->mid_value != NULL)
673 mailimf_msg_id_free(message_id->mid_value);
674 free(message_id);
675}
676
677struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list)
678{
679 struct mailimf_in_reply_to * in_reply_to;
680
681 in_reply_to = malloc(sizeof(* in_reply_to));
682 if (in_reply_to == NULL)
683 return NULL;
684
685 in_reply_to->mid_list = mid_list;
686
687 return in_reply_to;
688}
689
690void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to)
691{
692 clist_foreach(in_reply_to->mid_list,
693 (clist_func) mailimf_msg_id_free, NULL);
694 clist_free(in_reply_to->mid_list);
695 free(in_reply_to);
696}
697
698struct mailimf_references * mailimf_references_new(clist * mid_list)
699{
700 struct mailimf_references * ref;
701
702 ref = malloc(sizeof(* ref));
703 if (ref == NULL)
704 return NULL;
705
706 ref->mid_list = mid_list;
707
708 return ref;
709}
710
711void mailimf_references_free(struct mailimf_references * references)
712{
713 clist_foreach(references->mid_list,
714 (clist_func) mailimf_msg_id_free, NULL);
715 clist_free(references->mid_list);
716 free(references);
717}
718
719void mailimf_msg_id_free(char * msg_id)
720{
721 free(msg_id);
722}
723
724void mailimf_id_left_free(char * id_left)
725{
726 free(id_left);
727}
728
729void mailimf_id_right_free(char * id_right)
730{
731 free(id_right);
732}
733
734void mailimf_no_fold_quote_free(char * nfq)
735{
736 free(nfq);
737}
738
739void mailimf_no_fold_literal_free(char * nfl)
740{
741 free(nfl);
742}
743
744struct mailimf_subject * mailimf_subject_new(char * sbj_value)
745{
746 struct mailimf_subject * subject;
747
748 subject = malloc(sizeof(* subject));
749 if (subject == NULL)
750 return NULL;
751
752 subject->sbj_value = sbj_value;
753
754 return subject;
755}
756
757void mailimf_subject_free(struct mailimf_subject * subject)
758{
759 mailimf_unstructured_free(subject->sbj_value);
760 free(subject);
761}
762
763struct mailimf_comments * mailimf_comments_new(char * cm_value)
764{
765 struct mailimf_comments * comments;
766
767 comments = malloc(sizeof(* comments));
768 if (comments == NULL)
769 return NULL;
770
771 comments->cm_value = cm_value;
772
773 return comments;
774}
775
776void mailimf_comments_free(struct mailimf_comments * comments)
777{
778 mailimf_unstructured_free(comments->cm_value);
779 free(comments);
780}
781
782struct mailimf_keywords * mailimf_keywords_new(clist * kw_list)
783{
784 struct mailimf_keywords * keywords;
785
786 keywords = malloc(sizeof(* keywords));
787 if (keywords == NULL)
788 return NULL;
789
790 keywords->kw_list = kw_list;
791
792 return keywords;
793}
794
795void mailimf_keywords_free(struct mailimf_keywords * keywords)
796{
797 clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL);
798 clist_free(keywords->kw_list);
799 free(keywords);
800}
801
802struct mailimf_return *
803mailimf_return_new(struct mailimf_path * ret_path)
804{
805 struct mailimf_return * return_path;
806
807 return_path = malloc(sizeof(* return_path));
808 if (return_path == NULL)
809 return NULL;
810
811 return_path->ret_path = ret_path;
812
813 return return_path;
814}
815
816void mailimf_return_free(struct mailimf_return * return_path)
817{
818 mailimf_path_free(return_path->ret_path);
819 free(return_path);
820}
821
822
823struct mailimf_path * mailimf_path_new(char * pt_addr_spec)
824{
825 struct mailimf_path * path;
826
827 path = malloc(sizeof(* path));
828 if (path == NULL)
829 return NULL;
830
831 path->pt_addr_spec = pt_addr_spec;
832
833 return path;
834}
835
836void mailimf_path_free(struct mailimf_path * path)
837{
838 if (path->pt_addr_spec != NULL)
839 mailimf_addr_spec_free(path->pt_addr_spec);
840 free(path);
841}
842
843struct mailimf_optional_field *
844mailimf_optional_field_new(char * fld_name, char * fld_value)
845{
846 struct mailimf_optional_field * opt_field;
847
848 opt_field = malloc(sizeof(* opt_field));
849 if (opt_field == NULL)
850 return NULL;
851
852 opt_field->fld_name = fld_name;
853 opt_field->fld_value = fld_value;
854
855 return opt_field;
856}
857
858void mailimf_optional_field_free(struct mailimf_optional_field * opt_field)
859{
860 mailimf_field_name_free(opt_field->fld_name);
861 mailimf_unstructured_free(opt_field->fld_value);
862 free(opt_field);
863}
864
865void mailimf_field_name_free(char * field_name)
866{
867 free(field_name);
868}
diff --git a/libetpan/src/low-level/imf/mailimf_types.h b/libetpan/src/low-level/imf/mailimf_types.h
new file mode 100644
index 0000000..e73db48
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types.h
@@ -0,0 +1,793 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32
33/*
34 * $Id$
35 */
36
37#ifndef MAILIMF_TYPES_H
38
39#define MAILIMF_TYPES_H
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45#include <libetpan/clist.h>
46#include <sys/types.h>
47
48/*
49 IMPORTANT NOTE:
50
51 All allocation functions will take as argument allocated data
52 and will store these data in the structure they will allocate.
53 Data should be persistant during all the use of the structure
54 and will be freed by the free function of the structure
55
56 allocation functions will return NULL on failure
57*/
58
59/*
60 mailimf_date_time is a date
61
62 - day is the day of month (1 to 31)
63
64 - month (1 to 12)
65
66 - year (4 digits)
67
68 - hour (0 to 23)
69
70 - min (0 to 59)
71
72 - sec (0 to 59)
73
74 - zone (this is the decimal value that we can read, for example:
75 for "-0200", the value is -200)
76*/
77
78struct mailimf_date_time {
79 int dt_day;
80 int dt_month;
81 int dt_year;
82 int dt_hour;
83 int dt_min;
84 int dt_sec;
85 int dt_zone;
86};
87
88struct mailimf_date_time *
89mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
90 int dt_hour, int dt_min, int dt_sec, int dt_zone);
91
92void mailimf_date_time_free(struct mailimf_date_time * date_time);
93
94
95
96/* this is the type of address */
97
98enum {
99 MAILIMF_ADDRESS_ERROR, /* on parse error */
100 MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */
101 MAILIMF_ADDRESS_GROUP, /* if this is a group
102 (group_name: address1@domain1,
103 address2@domain2; ) */
104};
105
106/*
107 mailimf_address is an address
108
109 - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP
110
111 - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX
112
113 - group is a group if type is MAILIMF_ADDRESS_GROUP
114*/
115
116struct mailimf_address {
117 int ad_type;
118 union {
119 struct mailimf_mailbox * ad_mailbox; /* can be NULL */
120 struct mailimf_group * ad_group; /* can be NULL */
121 } ad_data;
122};
123
124
125struct mailimf_address *
126mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
127 struct mailimf_group * ad_group);
128
129void mailimf_address_free(struct mailimf_address * address);
130
131
132
133/*
134 mailimf_mailbox is a mailbox
135
136 - display_name is the name that will be displayed for this mailbox,
137 for example 'name' in '"name" <mailbox@domain>,
138 should be allocated with malloc()
139
140 - addr_spec is the mailbox, for example 'mailbox@domain'
141 in '"name" <mailbox@domain>, should be allocated with malloc()
142*/
143
144struct mailimf_mailbox {
145 char * mb_display_name; /* can be NULL */
146 char * mb_addr_spec; /* != NULL */
147};
148
149struct mailimf_mailbox *
150mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec);
151
152void mailimf_mailbox_free(struct mailimf_mailbox * mailbox);
153
154
155
156/*
157 mailimf_group is a group
158
159 - display_name is the name that will be displayed for this group,
160 for example 'group_name' in
161 'group_name: address1@domain1, address2@domain2;', should be allocated
162 with malloc()
163
164 - mb_list is a list of mailboxes
165*/
166
167struct mailimf_group {
168 char * grp_display_name; /* != NULL */
169 struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
170};
171
172struct mailimf_group *
173mailimf_group_new(char * grp_display_name,
174 struct mailimf_mailbox_list * grp_mb_list);
175
176void mailimf_group_free(struct mailimf_group * group);
177
178
179
180/*
181 mailimf_mailbox_list is a list of mailboxes
182
183 - list is a list of mailboxes
184*/
185
186struct mailimf_mailbox_list {
187 clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */
188};
189
190struct mailimf_mailbox_list *
191mailimf_mailbox_list_new(clist * mb_list);
192
193void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);
194
195
196
197/*
198 mailimf_address_list is a list of addresses
199
200 - list is a list of addresses
201*/
202
203struct mailimf_address_list {
204 clist * ad_list; /* list of (struct mailimf_address *), != NULL */
205};
206
207struct mailimf_address_list *
208mailimf_address_list_new(clist * ad_list);
209
210void mailimf_address_list_free(struct mailimf_address_list * addr_list);
211
212
213
214
215
216/*
217 mailimf_body is the text part of a message
218
219 - text is the beginning of the text part, it is a substring
220 of an other string
221
222 - size is the size of the text part
223*/
224
225struct mailimf_body {
226 const char * bd_text; /* != NULL */
227 size_t bd_size;
228};
229
230struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);
231
232void mailimf_body_free(struct mailimf_body * body);
233
234
235
236
237/*
238 mailimf_message is the content of the message
239
240 - msg_fields is the header fields of the message
241
242 - msg_body is the text part of the message
243*/
244
245struct mailimf_message {
246 struct mailimf_fields * msg_fields; /* != NULL */
247 struct mailimf_body * msg_body; /* != NULL */
248};
249
250struct mailimf_message *
251mailimf_message_new(struct mailimf_fields * msg_fields,
252 struct mailimf_body * msg_body);
253
254void mailimf_message_free(struct mailimf_message * message);
255
256
257
258
259/*
260 mailimf_fields is a list of header fields
261
262 - fld_list is a list of header fields
263*/
264
265struct mailimf_fields {
266 clist * fld_list; /* list of (struct mailimf_field *), != NULL */
267};
268
269struct mailimf_fields * mailimf_fields_new(clist * fld_list);
270
271void mailimf_fields_free(struct mailimf_fields * fields);
272
273
274
275/* this is a type of field */
276
277enum {
278 MAILIMF_FIELD_NONE, /* on parse error */
279 MAILIMF_FIELD_RETURN_PATH, /* Return-Path */
280 MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */
281 MAILIMF_FIELD_RESENT_FROM, /* Resent-From */
282 MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */
283 MAILIMF_FIELD_RESENT_TO, /* Resent-To */
284 MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */
285 MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */
286 MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */
287 MAILIMF_FIELD_ORIG_DATE, /* Date */
288 MAILIMF_FIELD_FROM, /* From */
289 MAILIMF_FIELD_SENDER, /* Sender */
290 MAILIMF_FIELD_REPLY_TO, /* Reply-To */
291 MAILIMF_FIELD_TO, /* To */
292 MAILIMF_FIELD_CC, /* Cc */
293 MAILIMF_FIELD_BCC, /* Bcc */
294 MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */
295 MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */
296 MAILIMF_FIELD_REFERENCES, /* References */
297 MAILIMF_FIELD_SUBJECT, /* Subject */
298 MAILIMF_FIELD_COMMENTS, /* Comments */
299 MAILIMF_FIELD_KEYWORDS, /* Keywords */
300 MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
301};
302
303/*
304 mailimf_field is a field
305
306 - fld_type is the type of the field
307
308 - fld_data.fld_return_path is the parsed content of the Return-Path
309 field if type is MAILIMF_FIELD_RETURN_PATH
310
311 - fld_data.fld_resent_date is the parsed content of the Resent-Date field
312 if type is MAILIMF_FIELD_RESENT_DATE
313
314 - fld_data.fld_resent_from is the parsed content of the Resent-From field
315
316 - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field
317
318 - fld_data.fld_resent_to is the parsed content of the Resent-To field
319
320 - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field
321
322 - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field
323
324 - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID
325 field
326
327 - fld_data.fld_orig_date is the parsed content of the Date field
328
329 - fld_data.fld_from is the parsed content of the From field
330
331 - fld_data.fld_sender is the parsed content of the Sender field
332
333 - fld_data.fld_reply_to is the parsed content of the Reply-To field
334
335 - fld_data.fld_to is the parsed content of the To field
336
337 - fld_data.fld_cc is the parsed content of the Cc field
338
339 - fld_data.fld_bcc is the parsed content of the Bcc field
340
341 - fld_data.fld_message_id is the parsed content of the Message-ID field
342
343 - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field
344
345 - fld_data.fld_references is the parsed content of the References field
346
347 - fld_data.fld_subject is the content of the Subject field
348
349 - fld_data.fld_comments is the content of the Comments field
350
351 - fld_data.fld_keywords is the parsed content of the Keywords field
352
353 - fld_data.fld_optional_field is an other field and is not parsed
354*/
355
356#define LIBETPAN_MAILIMF_FIELD_UNION
357
358struct mailimf_field {
359 int fld_type;
360 union {
361 struct mailimf_return * fld_return_path; /* can be NULL */
362 struct mailimf_orig_date * fld_resent_date; /* can be NULL */
363 struct mailimf_from * fld_resent_from; /* can be NULL */
364 struct mailimf_sender * fld_resent_sender; /* can be NULL */
365 struct mailimf_to * fld_resent_to; /* can be NULL */
366 struct mailimf_cc * fld_resent_cc; /* can be NULL */
367 struct mailimf_bcc * fld_resent_bcc; /* can be NULL */
368 struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
369 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
370 struct mailimf_from * fld_from; /* can be NULL */
371 struct mailimf_sender * fld_sender; /* can be NULL */
372 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
373 struct mailimf_to * fld_to; /* can be NULL */
374 struct mailimf_cc * fld_cc; /* can be NULL */
375 struct mailimf_bcc * fld_bcc; /* can be NULL */
376 struct mailimf_message_id * fld_message_id; /* can be NULL */
377 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
378 struct mailimf_references * fld_references; /* can be NULL */
379 struct mailimf_subject * fld_subject; /* can be NULL */
380 struct mailimf_comments * fld_comments; /* can be NULL */
381 struct mailimf_keywords * fld_keywords; /* can be NULL */
382 struct mailimf_optional_field * fld_optional_field; /* can be NULL */
383 } fld_data;
384};
385
386struct mailimf_field *
387mailimf_field_new(int fld_type,
388 struct mailimf_return * fld_return_path,
389 struct mailimf_orig_date * fld_resent_date,
390 struct mailimf_from * fld_resent_from,
391 struct mailimf_sender * fld_resent_sender,
392 struct mailimf_to * fld_resent_to,
393 struct mailimf_cc * fld_resent_cc,
394 struct mailimf_bcc * fld_resent_bcc,
395 struct mailimf_message_id * fld_resent_msg_id,
396 struct mailimf_orig_date * fld_orig_date,
397 struct mailimf_from * fld_from,
398 struct mailimf_sender * fld_sender,
399 struct mailimf_reply_to * fld_reply_to,
400 struct mailimf_to * fld_to,
401 struct mailimf_cc * fld_cc,
402 struct mailimf_bcc * fld_bcc,
403 struct mailimf_message_id * fld_message_id,
404 struct mailimf_in_reply_to * fld_in_reply_to,
405 struct mailimf_references * fld_references,
406 struct mailimf_subject * fld_subject,
407 struct mailimf_comments * fld_comments,
408 struct mailimf_keywords * fld_keywords,
409 struct mailimf_optional_field * fld_optional_field);
410
411void mailimf_field_free(struct mailimf_field * field);
412
413
414
415/*
416 mailimf_orig_date is the parsed Date field
417
418 - date_time is the parsed date
419*/
420
421struct mailimf_orig_date {
422 struct mailimf_date_time * dt_date_time; /* != NULL */
423};
424
425struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
426 dt_date_time);
427
428void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);
429
430
431
432
433/*
434 mailimf_from is the parsed From field
435
436 - mb_list is the parsed mailbox list
437*/
438
439struct mailimf_from {
440 struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
441};
442
443struct mailimf_from *
444mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);
445
446void mailimf_from_free(struct mailimf_from * from);
447
448
449
450/*
451 mailimf_sender is the parsed Sender field
452
453 - snd_mb is the parsed mailbox
454*/
455
456struct mailimf_sender {
457 struct mailimf_mailbox * snd_mb; /* != NULL */
458};
459
460struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);
461
462void mailimf_sender_free(struct mailimf_sender * sender);
463
464
465
466
467/*
468 mailimf_reply_to is the parsed Reply-To field
469
470 - rt_addr_list is the parsed address list
471 */
472
473struct mailimf_reply_to {
474 struct mailimf_address_list * rt_addr_list; /* != NULL */
475};
476
477struct mailimf_reply_to *
478mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);
479
480void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);
481
482
483
484
485/*
486 mailimf_to is the parsed To field
487
488 - to_addr_list is the parsed address list
489*/
490
491struct mailimf_to {
492 struct mailimf_address_list * to_addr_list; /* != NULL */
493};
494
495struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);
496
497void mailimf_to_free(struct mailimf_to * to);
498
499
500
501
502/*
503 mailimf_cc is the parsed Cc field
504
505 - cc_addr_list is the parsed addres list
506*/
507
508struct mailimf_cc {
509 struct mailimf_address_list * cc_addr_list; /* != NULL */
510};
511
512struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list);
513
514void mailimf_cc_free(struct mailimf_cc * cc);
515
516
517
518
519/*
520 mailimf_bcc is the parsed Bcc field
521
522 - bcc_addr_list is the parsed addres list
523*/
524
525struct mailimf_bcc {
526 struct mailimf_address_list * bcc_addr_list; /* can be NULL */
527};
528
529struct mailimf_bcc *
530mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);
531
532void mailimf_bcc_free(struct mailimf_bcc * bcc);
533
534
535
536/*
537 mailimf_message_id is the parsed Message-ID field
538
539 - mid_value is the message identifier
540*/
541
542struct mailimf_message_id {
543 char * mid_value; /* != NULL */
544};
545
546struct mailimf_message_id * mailimf_message_id_new(char * mid_value);
547
548void mailimf_message_id_free(struct mailimf_message_id * message_id);
549
550
551
552
553/*
554 mailimf_in_reply_to is the parsed In-Reply-To field
555
556 - mid_list is the list of message identifers
557*/
558
559struct mailimf_in_reply_to {
560 clist * mid_list; /* list of (char *), != NULL */
561};
562
563struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);
564
565void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);
566
567
568
569/*
570 mailimf_references is the parsed References field
571
572 - msg_id_list is the list of message identifiers
573 */
574
575struct mailimf_references {
576 clist * mid_list; /* list of (char *) */
577 /* != NULL */
578};
579
580struct mailimf_references * mailimf_references_new(clist * mid_list);
581
582void mailimf_references_free(struct mailimf_references * references);
583
584
585
586/*
587 mailimf_subject is the parsed Subject field
588
589 - sbj_value is the value of the field
590*/
591
592struct mailimf_subject {
593 char * sbj_value; /* != NULL */
594};
595
596struct mailimf_subject * mailimf_subject_new(char * sbj_value);
597
598void mailimf_subject_free(struct mailimf_subject * subject);
599
600
601/*
602 mailimf_comments is the parsed Comments field
603
604 - cm_value is the value of the field
605*/
606
607struct mailimf_comments {
608 char * cm_value; /* != NULL */
609};
610
611struct mailimf_comments * mailimf_comments_new(char * cm_value);
612
613void mailimf_comments_free(struct mailimf_comments * comments);
614
615
616/*
617 mailimf_keywords is the parsed Keywords field
618
619 - kw_list is the list of keywords
620*/
621
622struct mailimf_keywords {
623 clist * kw_list; /* list of (char *), != NULL */
624};
625
626struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);
627
628void mailimf_keywords_free(struct mailimf_keywords * keywords);
629
630
631/*
632 mailimf_return is the parsed Return-Path field
633
634 - ret_path is the parsed value of Return-Path
635*/
636
637struct mailimf_return {
638 struct mailimf_path * ret_path; /* != NULL */
639};
640
641struct mailimf_return *
642mailimf_return_new(struct mailimf_path * ret_path);
643
644void mailimf_return_free(struct mailimf_return * return_path);
645
646
647/*
648 mailimf_path is the parsed value of Return-Path
649
650 - pt_addr_spec is a mailbox
651*/
652
653struct mailimf_path {
654 char * pt_addr_spec; /* can be NULL */
655};
656
657struct mailimf_path * mailimf_path_new(char * pt_addr_spec);
658
659void mailimf_path_free(struct mailimf_path * path);
660
661
662/*
663 mailimf_optional_field is a non-parsed field
664
665 - fld_name is the name of the field
666
667 - fld_value is the value of the field
668*/
669
670struct mailimf_optional_field {
671 char * fld_name; /* != NULL */
672 char * fld_value; /* != NULL */
673};
674
675struct mailimf_optional_field *
676mailimf_optional_field_new(char * fld_name, char * fld_value);
677
678void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);
679
680
681/*
682 mailimf_fields is the native structure that IMF module will use,
683 this module will provide an easier structure to use when parsing fields.
684
685 mailimf_single_fields is an easier structure to get parsed fields,
686 rather than iteration over the list of fields
687
688 - fld_orig_date is the parsed "Date" field
689
690 - fld_from is the parsed "From" field
691
692 - fld_sender is the parsed "Sender "field
693
694 - fld_reply_to is the parsed "Reply-To" field
695
696 - fld_to is the parsed "To" field
697
698 - fld_cc is the parsed "Cc" field
699
700 - fld_bcc is the parsed "Bcc" field
701
702 - fld_message_id is the parsed "Message-ID" field
703
704 - fld_in_reply_to is the parsed "In-Reply-To" field
705
706 - fld_references is the parsed "References" field
707
708 - fld_subject is the parsed "Subject" field
709
710 - fld_comments is the parsed "Comments" field
711
712 - fld_keywords is the parsed "Keywords" field
713*/
714
715struct mailimf_single_fields {
716 struct mailimf_orig_date * fld_orig_date; /* can be NULL */
717 struct mailimf_from * fld_from; /* can be NULL */
718 struct mailimf_sender * fld_sender; /* can be NULL */
719 struct mailimf_reply_to * fld_reply_to; /* can be NULL */
720 struct mailimf_to * fld_to; /* can be NULL */
721 struct mailimf_cc * fld_cc; /* can be NULL */
722 struct mailimf_bcc * fld_bcc; /* can be NULL */
723 struct mailimf_message_id * fld_message_id; /* can be NULL */
724 struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */
725 struct mailimf_references * fld_references; /* can be NULL */
726 struct mailimf_subject * fld_subject; /* can be NULL */
727 struct mailimf_comments * fld_comments; /* can be NULL */
728 struct mailimf_keywords * fld_keywords; /* can be NULL */
729};
730
731
732
733
734
735
736/* internal use */
737
738void mailimf_atom_free(char * atom);
739
740void mailimf_dot_atom_free(char * dot_atom);
741
742void mailimf_dot_atom_text_free(char * dot_atom);
743
744void mailimf_quoted_string_free(char * quoted_string);
745
746void mailimf_word_free(char * word);
747
748void mailimf_phrase_free(char * phrase);
749
750void mailimf_unstructured_free(char * unstructured);
751
752void mailimf_angle_addr_free(char * angle_addr);
753
754void mailimf_display_name_free(char * display_name);
755
756void mailimf_addr_spec_free(char * addr_spec);
757
758void mailimf_local_part_free(char * local_part);
759
760void mailimf_domain_free(char * domain);
761
762void mailimf_domain_literal_free(char * domain);
763
764void mailimf_msg_id_free(char * msg_id);
765
766void mailimf_id_left_free(char * id_left);
767
768void mailimf_id_right_free(char * id_right);
769
770void mailimf_no_fold_quote_free(char * nfq);
771
772void mailimf_no_fold_literal_free(char * nfl);
773
774void mailimf_field_name_free(char * field_name);
775
776
777
778/* these are the possible returned error codes */
779
780enum {
781 MAILIMF_NO_ERROR = 0,
782 MAILIMF_ERROR_PARSE,
783 MAILIMF_ERROR_MEMORY,
784 MAILIMF_ERROR_INVAL,
785 MAILIMF_ERROR_FILE,
786};
787
788
789#ifdef __cplusplus
790}
791#endif
792
793#endif
diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.c b/libetpan/src/low-level/imf/mailimf_types_helper.c
new file mode 100644
index 0000000..a4f669c
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types_helper.c
@@ -0,0 +1,1636 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include "mailimf_types_helper.h"
33
34#include <stdlib.h>
35#include <string.h>
36#include <time.h>
37#include <unistd.h>
38
39#include "mailimf.h"
40
41struct mailimf_mailbox_list *
42mailimf_mailbox_list_new_empty()
43{
44 clist * list;
45 struct mailimf_mailbox_list * mb_list;
46
47 list = clist_new();
48 if (list == NULL)
49 return NULL;
50
51 mb_list = mailimf_mailbox_list_new(list);
52 if (mb_list == NULL)
53 return NULL;
54
55 return mb_list;
56}
57
58int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
59 struct mailimf_mailbox * mb)
60{
61 int r;
62
63 r = clist_append(mailbox_list->mb_list, mb);
64 if (r < 0)
65 return MAILIMF_ERROR_MEMORY;
66
67 return MAILIMF_NO_ERROR;
68}
69
70int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
71 char * mb_str)
72{
73 int r;
74 size_t cur_token;
75 struct mailimf_mailbox * mb;
76 int res;
77
78 cur_token = 0;
79 r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb);
80 if (r != MAILIMF_NO_ERROR) {
81 res = r;
82 goto err;
83 }
84
85 r = mailimf_mailbox_list_add(mailbox_list, mb);
86 if (r != MAILIMF_NO_ERROR) {
87 res = r;
88 goto free;
89 }
90
91 return MAILIMF_NO_ERROR;
92
93 free:
94 mailimf_mailbox_free(mb);
95 err:
96 return res;
97}
98
99int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
100 char * display_name, char * address)
101{
102 int r;
103 struct mailimf_mailbox * mb;
104 int res;
105
106 mb = mailimf_mailbox_new(display_name, address);
107 if (mb == NULL) {
108 res = MAILIMF_ERROR_MEMORY;
109 goto err;
110 }
111
112 r = mailimf_mailbox_list_add(mailbox_list, mb);
113 if (r != MAILIMF_NO_ERROR) {
114 res = r;
115 goto free;
116 }
117
118 return MAILIMF_NO_ERROR;
119
120 free:
121 mailimf_mailbox_free(mb);
122 err:
123 return res;
124}
125
126
127
128struct mailimf_address_list *
129mailimf_address_list_new_empty()
130{
131 clist * list;
132 struct mailimf_address_list * addr_list;
133
134 list = clist_new();
135 if (list == NULL)
136 return NULL;
137
138 addr_list = mailimf_address_list_new(list);
139 if (addr_list == NULL)
140 return NULL;
141
142 return addr_list;
143}
144
145int mailimf_address_list_add(struct mailimf_address_list * address_list,
146 struct mailimf_address * addr)
147{
148 int r;
149
150 r = clist_append(address_list->ad_list, addr);
151 if (r < 0)
152 return MAILIMF_ERROR_MEMORY;
153
154 return MAILIMF_NO_ERROR;
155}
156
157int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
158 char * addr_str)
159{
160 int r;
161 size_t cur_token;
162 struct mailimf_address * addr;
163 int res;
164
165 cur_token = 0;
166 r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr);
167 if (r != MAILIMF_NO_ERROR) {
168 res = r;
169 goto err;
170 }
171
172 r = mailimf_address_list_add(address_list, addr);
173 if (r != MAILIMF_NO_ERROR) {
174 res = r;
175 goto free;
176 }
177
178 return MAILIMF_NO_ERROR;
179
180 free:
181 mailimf_address_free(addr);
182 err:
183 return res;
184}
185
186int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
187 char * display_name, char * address)
188{
189 int r;
190 struct mailimf_mailbox * mb;
191 struct mailimf_address * addr;
192 int res;
193
194 mb = mailimf_mailbox_new(display_name, address);
195 if (mb == NULL) {
196 res = MAILIMF_ERROR_MEMORY;
197 goto err;
198 }
199
200 addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
201 if (addr == NULL) {
202 res = MAILIMF_ERROR_MEMORY;
203 goto free_mb;
204 }
205
206 r = mailimf_address_list_add(address_list, addr);
207 if (r != MAILIMF_NO_ERROR) {
208 res = r;
209 goto free_addr;
210 }
211
212 return MAILIMF_NO_ERROR;
213
214 free_addr:
215 mailimf_address_free(addr);
216 free_mb:
217 mailimf_mailbox_free(mb);
218 err:
219 return res;
220}
221
222
223#if 0
224struct mailimf_resent_fields_list *
225mailimf_resent_fields_list_new_empty()
226{
227 clist * list;
228 struct mailimf_resent_fields_list * rf_list;
229
230 list = clist_new();
231 if (list == NULL)
232 return NULL;
233
234 rf_list = mailimf_resent_fields_list_new(list);
235 if (rf_list == NULL)
236 return NULL;
237
238 return rf_list;
239}
240
241int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields,
242 struct mailimf_resent_field * field)
243{
244 int r;
245
246 r = clist_append(fields->list, field);
247 if (r < 0)
248 return MAILIMF_ERROR_MEMORY;
249
250 return MAILIMF_NO_ERROR;
251}
252#endif
253
254
255static void detach_free_common_fields(struct mailimf_orig_date * imf_date,
256 struct mailimf_from * imf_from,
257 struct mailimf_sender * imf_sender,
258 struct mailimf_to * imf_to,
259 struct mailimf_cc * imf_cc,
260 struct mailimf_bcc * imf_bcc,
261 struct mailimf_message_id * imf_msg_id)
262{
263 if (imf_date != NULL) {
264 imf_date->dt_date_time = NULL;
265 mailimf_orig_date_free(imf_date);
266 }
267 if (imf_from != NULL) {
268 imf_from->frm_mb_list = NULL;
269 mailimf_from_free(imf_from);
270 }
271 if (imf_sender != NULL) {
272 imf_sender->snd_mb = NULL;
273 mailimf_sender_free(imf_sender);
274 }
275 if (imf_to != NULL) {
276 imf_to->to_addr_list = NULL;
277 mailimf_to_free(imf_to);
278 }
279 if (imf_cc != NULL) {
280 imf_cc->cc_addr_list = NULL;
281 mailimf_to_free(imf_to);
282 }
283 if (imf_bcc != NULL) {
284 imf_bcc->bcc_addr_list = NULL;
285 mailimf_bcc_free(imf_bcc);
286 }
287 if (imf_msg_id != NULL) {
288 imf_msg_id->mid_value = NULL;
289 mailimf_message_id_free(imf_msg_id);
290 }
291}
292
293static void detach_resent_field(struct mailimf_field * field)
294{
295 field->fld_type = MAILIMF_FIELD_NONE;
296 mailimf_field_free(field);
297}
298
299int
300mailimf_resent_fields_add_data(struct mailimf_fields * fields,
301 struct mailimf_date_time * resent_date,
302 struct mailimf_mailbox_list * resent_from,
303 struct mailimf_mailbox * resent_sender,
304 struct mailimf_address_list * resent_to,
305 struct mailimf_address_list * resent_cc,
306 struct mailimf_address_list * resent_bcc,
307 char * resent_msg_id)
308{
309 struct mailimf_orig_date * imf_resent_date;
310 struct mailimf_from * imf_resent_from;
311 struct mailimf_sender * imf_resent_sender;
312 struct mailimf_to * imf_resent_to;
313 struct mailimf_cc * imf_resent_cc;
314 struct mailimf_bcc * imf_resent_bcc;
315 struct mailimf_message_id * imf_resent_msg_id;
316 struct mailimf_field * field;
317 int r;
318
319 imf_resent_date = NULL;
320 imf_resent_from = NULL;
321 imf_resent_sender = NULL;
322 imf_resent_to = NULL;
323 imf_resent_cc = NULL;
324 imf_resent_bcc = NULL;
325 imf_resent_msg_id = NULL;
326 field = NULL;
327
328 if (resent_date != NULL) {
329 imf_resent_date = mailimf_orig_date_new(resent_date);
330 if (imf_resent_date == NULL)
331 goto free;
332 field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE,
333 NULL /* return-path */,
334 imf_resent_date /* resent date */,
335 NULL /* resent from */,
336 NULL /* resent sender */,
337 NULL /* resent to */,
338 NULL /* resent cc */,
339 NULL /* resent bcc */,
340 NULL /* resent msg id */,
341 NULL /* date */,
342 NULL /* from */,
343 NULL /* sender */,
344 NULL /* reply-to */,
345 NULL /* to */,
346 NULL /* cc */,
347 NULL /* bcc */,
348 NULL /* message id */,
349 NULL /* in reply to */,
350 NULL /* references */,
351 NULL /* subject */,
352 NULL /* comments */,
353 NULL /* keywords */,
354 NULL /* optional field */);
355 if (field == NULL)
356 goto free;
357 r = mailimf_fields_add(fields, field);
358 if (r != MAILIMF_NO_ERROR)
359 goto free_field;
360 }
361
362 if (resent_from != NULL) {
363 imf_resent_from = mailimf_from_new(resent_from);
364 if (imf_resent_from == NULL)
365 goto free_field;
366 field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM,
367 NULL /* return-path */,
368 NULL /* resent date */,
369 imf_resent_from /* resent from */,
370 NULL /* resent sender */,
371 NULL /* resent to */,
372 NULL /* resent cc */,
373 NULL /* resent bcc */,
374 NULL /* resent msg id */,
375 NULL /* date */,
376 NULL /* from */,
377 NULL /* sender */,
378 NULL /* reply-to */,
379 NULL /* to */,
380 NULL /* cc */,
381 NULL /* bcc */,
382 NULL /* message id */,
383 NULL /* in reply to */,
384 NULL /* references */,
385 NULL /* subject */,
386 NULL /* comments */,
387 NULL /* keywords */,
388 NULL /* optional field */);
389 if (field == NULL)
390 goto free;
391 r = mailimf_fields_add(fields, field);
392 if (r != MAILIMF_NO_ERROR)
393 goto free_field;
394 }
395
396 if (resent_sender != NULL) {
397 imf_resent_sender = mailimf_sender_new(resent_sender);
398 if (imf_resent_sender == NULL)
399 goto free;
400 field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER,
401 NULL /* return-path */,
402 NULL /* resent date */,
403 NULL /* resent from */,
404 imf_resent_sender /* resent sender */,
405 NULL /* resent to */,
406 NULL /* resent cc */,
407 NULL /* resent bcc */,
408 NULL /* resent msg id */,
409 NULL /* date */,
410 NULL /* from */,
411 NULL /* sender */,
412 NULL /* reply-to */,
413 NULL /* to */,
414 NULL /* cc */,
415 NULL /* bcc */,
416 NULL /* message id */,
417 NULL /* in reply to */,
418 NULL /* references */,
419 NULL /* subject */,
420 NULL /* comments */,
421 NULL /* keywords */,
422 NULL /* optional field */);
423 if (field == NULL)
424 goto free;
425 r = mailimf_fields_add(fields, field);
426 if (r != MAILIMF_NO_ERROR)
427 goto free_field;
428 }
429
430 if (resent_to != NULL) {
431 imf_resent_to = mailimf_to_new(resent_to);
432 if (imf_resent_to == NULL)
433 goto free;
434 field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO,
435 NULL /* return-path */,
436 NULL /* resent date */,
437 NULL /* resent from */,
438 NULL /* resent sender */,
439 imf_resent_to /* resent to */,
440 NULL /* resent cc */,
441 NULL /* resent bcc */,
442 NULL /* resent msg id */,
443 NULL /* date */,
444 NULL /* from */,
445 NULL /* sender */,
446 NULL /* reply-to */,
447 NULL /* to */,
448 NULL /* cc */,
449 NULL /* bcc */,
450 NULL /* message id */,
451 NULL /* in reply to */,
452 NULL /* references */,
453 NULL /* subject */,
454 NULL /* comments */,
455 NULL /* keywords */,
456 NULL /* optional field */);
457 if (field == NULL)
458 goto free;
459 r = mailimf_fields_add(fields, field);
460 if (r != MAILIMF_NO_ERROR)
461 goto free_field;
462 }
463
464 if (resent_cc != NULL) {
465 imf_resent_cc = mailimf_cc_new(resent_cc);
466 if (imf_resent_cc == NULL)
467 goto free;
468 field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC,
469 NULL /* return-path */,
470 NULL /* resent date */,
471 NULL /* resent from */,
472 NULL /* resent sender */,
473 NULL /* resent to */,
474 imf_resent_cc /* resent cc */,
475 NULL /* resent bcc */,
476 NULL /* resent msg id */,
477 NULL /* date */,
478 NULL /* from */,
479 NULL /* sender */,
480 NULL /* reply-to */,
481 NULL /* to */,
482 NULL /* cc */,
483 NULL /* bcc */,
484 NULL /* message id */,
485 NULL /* in reply to */,
486 NULL /* references */,
487 NULL /* subject */,
488 NULL /* comments */,
489 NULL /* keywords */,
490 NULL /* optional field */);
491 if (field == NULL)
492 goto free;
493 r = mailimf_fields_add(fields, field);
494 if (r != MAILIMF_NO_ERROR)
495 goto free_field;
496 }
497
498 if (resent_bcc != NULL) {
499 imf_resent_bcc = mailimf_bcc_new(resent_bcc);
500 if (imf_resent_bcc == NULL)
501 goto free;
502 field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC,
503 NULL /* return-path */,
504 NULL /* resent date */,
505 NULL /* resent from */,
506 NULL /* resent sender */,
507 NULL /* resent to */,
508 NULL /* resent cc */,
509 imf_resent_bcc /* resent bcc */,
510 NULL /* resent msg id */,
511 NULL /* date */,
512 NULL /* from */,
513 NULL /* sender */,
514 NULL /* reply-to */,
515 NULL /* to */,
516 NULL /* cc */,
517 NULL /* bcc */,
518 NULL /* message id */,
519 NULL /* in reply to */,
520 NULL /* references */,
521 NULL /* subject */,
522 NULL /* comments */,
523 NULL /* keywords */,
524 NULL /* optional field */);
525 if (field == NULL)
526 goto free;
527 r = mailimf_fields_add(fields, field);
528 if (r != MAILIMF_NO_ERROR)
529 goto free_field;
530 }
531
532 if (resent_msg_id != NULL) {
533 imf_resent_msg_id = mailimf_message_id_new(resent_msg_id);
534 if (imf_resent_msg_id == NULL)
535 goto free;
536 field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID,
537 NULL /* return-path */,
538 NULL /* resent date */,
539 NULL /* resent from */,
540 NULL /* resent sender */,
541 NULL /* resent to */,
542 NULL /* resent cc */,
543 NULL /* resent bcc */,
544 imf_resent_msg_id /* resent msg id */,
545 NULL /* date */,
546 NULL /* from */,
547 NULL /* sender */,
548 NULL /* reply-to */,
549 NULL /* to */,
550 NULL /* cc */,
551 NULL /* bcc */,
552 NULL /* message id */,
553 NULL /* in reply to */,
554 NULL /* references */,
555 NULL /* subject */,
556 NULL /* comments */,
557 NULL /* keywords */,
558 NULL /* optional field */);
559 if (field == NULL)
560 goto free;
561 r = mailimf_fields_add(fields, field);
562 if (r != MAILIMF_NO_ERROR)
563 goto free_field;
564 }
565
566 return MAILIMF_NO_ERROR;
567
568 free_field:
569 if (field != NULL) {
570 detach_resent_field(field);
571 mailimf_field_free(field);
572 }
573 free:
574 detach_free_common_fields(imf_resent_date,
575 imf_resent_from,
576 imf_resent_sender,
577 imf_resent_to,
578 imf_resent_cc,
579 imf_resent_bcc,
580 imf_resent_msg_id);
581 return MAILIMF_ERROR_MEMORY;
582}
583
584struct mailimf_fields *
585mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
586 resent_date,
587 struct mailimf_mailbox_list *
588 resent_from,
589 struct mailimf_mailbox *
590 resent_sender,
591 struct mailimf_address_list *
592 resent_to,
593 struct mailimf_address_list *
594 resent_cc,
595 struct mailimf_address_list *
596 resent_bcc,
597 char * resent_msg_id)
598{
599 struct mailimf_fields * resent_fields;
600 int r;
601
602 resent_fields = mailimf_fields_new_empty();
603 if (resent_fields == NULL)
604 goto err;
605
606 r = mailimf_resent_fields_add_data(resent_fields,
607 resent_date, resent_from,
608 resent_sender, resent_to,
609 resent_cc, resent_bcc,
610 resent_msg_id);
611 if (r != MAILIMF_NO_ERROR)
612 goto free;
613
614 return resent_fields;
615
616 free:
617 mailimf_fields_free(resent_fields);
618 err:
619 return NULL;
620}
621
622
623struct mailimf_fields *
624mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
625 struct mailimf_mailbox * sender,
626 struct mailimf_address_list * to,
627 struct mailimf_address_list * cc,
628 struct mailimf_address_list * bcc)
629{
630 struct mailimf_date_time * date;
631 char * msg_id;
632 struct mailimf_fields * fields;
633
634 date = mailimf_get_current_date();
635 if (date == NULL)
636 goto err;
637
638 msg_id = mailimf_get_message_id();
639 if (msg_id == NULL)
640 goto free_date;
641
642 fields = mailimf_resent_fields_new_with_data_all(date,
643 from, sender, to, cc, bcc, msg_id);
644 if (fields == NULL)
645 goto free_msg_id;
646
647 return fields;
648
649 free_msg_id:
650 free(msg_id);
651 free_date:
652 mailimf_date_time_free(date);
653 err:
654 return NULL;
655}
656
657
658struct mailimf_fields *
659mailimf_fields_new_empty(void)
660{
661 clist * list;
662 struct mailimf_fields * fields_list;
663
664 list = clist_new();
665 if (list == NULL)
666 return NULL;
667
668 fields_list = mailimf_fields_new(list);
669 if (fields_list == NULL)
670 return NULL;
671
672 return fields_list;
673}
674
675int mailimf_fields_add(struct mailimf_fields * fields,
676 struct mailimf_field * field)
677{
678 int r;
679
680 r = clist_append(fields->fld_list, field);
681 if (r < 0)
682 return MAILIMF_ERROR_MEMORY;
683
684 return MAILIMF_NO_ERROR;
685}
686
687static void detach_free_fields(struct mailimf_orig_date * date,
688 struct mailimf_from * from,
689 struct mailimf_sender * sender,
690 struct mailimf_reply_to * reply_to,
691 struct mailimf_to * to,
692 struct mailimf_cc * cc,
693 struct mailimf_bcc * bcc,
694 struct mailimf_message_id * msg_id,
695 struct mailimf_in_reply_to * in_reply_to,
696 struct mailimf_references * references,
697 struct mailimf_subject * subject)
698{
699 detach_free_common_fields(date,
700 from,
701 sender,
702 to,
703 cc,
704 bcc,
705 msg_id);
706
707 if (reply_to != NULL) {
708 reply_to->rt_addr_list = NULL;
709 mailimf_reply_to_free(reply_to);
710 }
711
712 if (in_reply_to != NULL) {
713 in_reply_to->mid_list = NULL;
714 mailimf_in_reply_to_free(in_reply_to);
715 }
716
717 if (references != NULL) {
718 references->mid_list = NULL;
719 mailimf_references_free(references);
720 }
721
722 if (subject != NULL) {
723 subject->sbj_value = NULL;
724 mailimf_subject_free(subject);
725 }
726}
727
728
729static void detach_field(struct mailimf_field * field)
730{
731 field->fld_type = MAILIMF_FIELD_NONE;
732 mailimf_field_free(field);
733}
734
735int mailimf_fields_add_data(struct mailimf_fields * fields,
736 struct mailimf_date_time * date,
737 struct mailimf_mailbox_list * from,
738 struct mailimf_mailbox * sender,
739 struct mailimf_address_list * reply_to,
740 struct mailimf_address_list * to,
741 struct mailimf_address_list * cc,
742 struct mailimf_address_list * bcc,
743 char * msg_id,
744 clist * in_reply_to,
745 clist * references,
746 char * subject)
747{
748 struct mailimf_orig_date * imf_date;
749 struct mailimf_from * imf_from;
750 struct mailimf_sender * imf_sender;
751 struct mailimf_reply_to * imf_reply_to;
752 struct mailimf_to * imf_to;
753 struct mailimf_cc * imf_cc;
754 struct mailimf_bcc * imf_bcc;
755 struct mailimf_message_id * imf_msg_id;
756 struct mailimf_references * imf_references;
757 struct mailimf_in_reply_to * imf_in_reply_to;
758 struct mailimf_subject * imf_subject;
759 struct mailimf_field * field;
760 int r;
761
762 imf_date = NULL;
763 imf_from = NULL;
764 imf_sender = NULL;
765 imf_reply_to = NULL;
766 imf_to = NULL;
767 imf_cc = NULL;
768 imf_bcc = NULL;
769 imf_msg_id = NULL;
770 imf_references = NULL;
771 imf_in_reply_to = NULL;
772 imf_subject =NULL;
773 field = NULL;
774
775 if (date != NULL) {
776 imf_date = mailimf_orig_date_new(date);
777 if (imf_date == NULL)
778 goto free;
779 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
780 NULL /* return-path */,
781 NULL /* resent date */,
782 NULL /* resent from */,
783 NULL /* resent sender */,
784 NULL /* resent to */,
785 NULL /* resent cc */,
786 NULL /* resent bcc */,
787 NULL /* resent msg id */,
788 imf_date /* date */,
789 NULL /* from */,
790 NULL /* sender */,
791 NULL /* reply-to */,
792 NULL /* to */,
793 NULL /* cc */,
794 NULL /* bcc */,
795 NULL /* message id */,
796 NULL /* in reply to */,
797 NULL /* references */,
798 NULL /* subject */,
799 NULL /* comments */,
800 NULL /* keywords */,
801 NULL /* optional field */);
802 if (field == NULL)
803 goto free;
804 r = mailimf_fields_add(fields, field);
805 if (r != MAILIMF_NO_ERROR)
806 goto free_field;
807 }
808
809 if (from != NULL) {
810 imf_from = mailimf_from_new(from);
811 if (imf_from == NULL)
812 goto free_field;
813 field = mailimf_field_new(MAILIMF_FIELD_FROM,
814 NULL /* return-path */,
815 NULL /* resent date */,
816 NULL /* resent from */,
817 NULL /* resent sender */,
818 NULL /* resent to */,
819 NULL /* resent cc */,
820 NULL /* resent bcc */,
821 NULL /* resent msg id */,
822 NULL /* date */,
823 imf_from /* from */,
824 NULL /* sender */,
825 NULL /* reply-to */,
826 NULL /* to */,
827 NULL /* cc */,
828 NULL /* bcc */,
829 NULL /* message id */,
830 NULL /* in reply to */,
831 NULL /* references */,
832 NULL /* subject */,
833 NULL /* comments */,
834 NULL /* keywords */,
835 NULL /* optional field */);
836 if (field == NULL)
837 goto free;
838 r = mailimf_fields_add(fields, field);
839 if (r != MAILIMF_NO_ERROR)
840 goto free_field;
841 }
842
843 if (sender != NULL) {
844 imf_sender = mailimf_sender_new(sender);
845 if (imf_sender == NULL)
846 goto free;
847 field = mailimf_field_new(MAILIMF_FIELD_SENDER,
848 NULL /* return-path */,
849 NULL /* resent date */,
850 NULL /* resent from */,
851 NULL /* resent sender */,
852 NULL /* resent to */,
853 NULL /* resent cc */,
854 NULL /* resent bcc */,
855 NULL /* resent msg id */,
856 NULL /* date */,
857 NULL /* from */,
858 imf_sender /* sender */,
859 NULL /* reply-to */,
860 NULL /* to */,
861 NULL /* cc */,
862 NULL /* bcc */,
863 NULL /* message id */,
864 NULL /* in reply to */,
865 NULL /* references */,
866 NULL /* subject */,
867 NULL /* comments */,
868 NULL /* keywords */,
869 NULL /* optional field */);
870 if (field == NULL)
871 goto free;
872 r = mailimf_fields_add(fields, field);
873 if (r != MAILIMF_NO_ERROR)
874 goto free_field;
875 }
876
877 if (reply_to != NULL) {
878 imf_reply_to = mailimf_reply_to_new(reply_to);
879 if (imf_reply_to == NULL)
880 goto free;
881 field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
882 NULL /* return-path */,
883 NULL /* resent date */,
884 NULL /* resent from */,
885 NULL /* resent sender */,
886 NULL /* resent to */,
887 NULL /* resent cc */,
888 NULL /* resent bcc */,
889 NULL /* resent msg id */,
890 NULL /* date */,
891 NULL /* from */,
892 NULL /* sender */,
893 imf_reply_to /* reply-to */,
894 NULL /* to */,
895 NULL /* cc */,
896 NULL /* bcc */,
897 NULL /* message id */,
898 NULL /* in reply to */,
899 NULL /* references */,
900 NULL /* subject */,
901 NULL /* comments */,
902 NULL /* keywords */,
903 NULL /* optional field */);
904 if (field == NULL)
905 goto free;
906 r = mailimf_fields_add(fields, field);
907 if (r != MAILIMF_NO_ERROR)
908 goto free_field;
909 }
910
911 if (to != NULL) {
912 imf_to = mailimf_to_new(to);
913 if (imf_to == NULL)
914 goto free;
915 field = mailimf_field_new(MAILIMF_FIELD_TO,
916 NULL /* return-path */,
917 NULL /* resent date */,
918 NULL /* resent from */,
919 NULL /* resent sender */,
920 NULL /* resent to */,
921 NULL /* resent cc */,
922 NULL /* resent bcc */,
923 NULL /* resent msg id */,
924 NULL /* date */,
925 NULL /* from */,
926 NULL /* sender */,
927 NULL /* reply-to */,
928 imf_to /* to */,
929 NULL /* cc */,
930 NULL /* bcc */,
931 NULL /* message id */,
932 NULL /* in reply to */,
933 NULL /* references */,
934 NULL /* subject */,
935 NULL /* comments */,
936 NULL /* keywords */,
937 NULL /* optional field */);
938 if (field == NULL)
939 goto free;
940 r = mailimf_fields_add(fields, field);
941 if (r != MAILIMF_NO_ERROR)
942 goto free_field;
943 }
944
945 if (cc != NULL) {
946 imf_cc = mailimf_cc_new(cc);
947 if (imf_cc == NULL)
948 goto free;
949 field = mailimf_field_new(MAILIMF_FIELD_CC,
950 NULL /* return-path */,
951 NULL /* resent date */,
952 NULL /* resent from */,
953 NULL /* resent sender */,
954 NULL /* resent to */,
955 NULL /* resent cc */,
956 NULL /* resent bcc */,
957 NULL /* resent msg id */,
958 NULL /* date */,
959 NULL /* from */,
960 NULL /* sender */,
961 NULL /* reply-to */,
962 NULL /* to */,
963 imf_cc /* cc */,
964 NULL /* bcc */,
965 NULL /* message id */,
966 NULL /* in reply to */,
967 NULL /* references */,
968 NULL /* subject */,
969 NULL /* comments */,
970 NULL /* keywords */,
971 NULL /* optional field */);
972 if (field == NULL)
973 goto free;
974 r = mailimf_fields_add(fields, field);
975 if (r != MAILIMF_NO_ERROR)
976 goto free_field;
977 }
978
979 if (bcc != NULL) {
980 imf_bcc = mailimf_bcc_new(bcc);
981 if (imf_bcc == NULL)
982 goto free;
983 field = mailimf_field_new(MAILIMF_FIELD_BCC,
984 NULL /* return-path */,
985 NULL /* resent date */,
986 NULL /* resent from */,
987 NULL /* resent sender */,
988 NULL /* resent to */,
989 NULL /* resent cc */,
990 NULL /* resent bcc */,
991 NULL /* resent msg id */,
992 NULL /* date */,
993 NULL /* from */,
994 NULL /* sender */,
995 NULL /* reply-to */,
996 NULL /* to */,
997 NULL /* cc */,
998 imf_bcc /* bcc */,
999 NULL /* message id */,
1000 NULL /* in reply to */,
1001 NULL /* references */,
1002 NULL /* subject */,
1003 NULL /* comments */,
1004 NULL /* keywords */,
1005 NULL /* optional field */);
1006 if (field == NULL)
1007 goto free;
1008 r = mailimf_fields_add(fields, field);
1009 if (r != MAILIMF_NO_ERROR)
1010 goto free_field;
1011 }
1012
1013 if (msg_id != NULL) {
1014 imf_msg_id = mailimf_message_id_new(msg_id);
1015 if (imf_msg_id == NULL)
1016 goto free;
1017 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1018 NULL /* return-path */,
1019 NULL /* resent date */,
1020 NULL /* resent from */,
1021 NULL /* resent sender */,
1022 NULL /* resent to */,
1023 NULL /* resent cc */,
1024 NULL /* resent bcc */,
1025 NULL /* resent msg id */,
1026 NULL /* date */,
1027 NULL /* from */,
1028 NULL /* sender */,
1029 NULL /* reply-to */,
1030 NULL /* to */,
1031 NULL /* cc */,
1032 NULL /* bcc */,
1033 imf_msg_id /* message id */,
1034 NULL /* in reply to */,
1035 NULL /* references */,
1036 NULL /* subject */,
1037 NULL /* comments */,
1038 NULL /* keywords */,
1039 NULL /* optional field */);
1040 if (field == NULL)
1041 goto free;
1042 r = mailimf_fields_add(fields, field);
1043 if (r != MAILIMF_NO_ERROR)
1044 goto free_field;
1045 }
1046
1047 if (in_reply_to != NULL) {
1048 imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to);
1049 if (imf_in_reply_to == NULL)
1050 goto free;
1051 field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
1052 NULL /* return-path */,
1053 NULL /* resent date */,
1054 NULL /* resent from */,
1055 NULL /* resent sender */,
1056 NULL /* resent to */,
1057 NULL /* resent cc */,
1058 NULL /* resent bcc */,
1059 NULL /* resent msg id */,
1060 NULL /* date */,
1061 NULL /* from */,
1062 NULL /* sender */,
1063 NULL /* reply-to */,
1064 NULL /* to */,
1065 NULL /* cc */,
1066 NULL /* bcc */,
1067 NULL /* message id */,
1068 imf_in_reply_to /* in reply to */,
1069 NULL /* references */,
1070 NULL /* subject */,
1071 NULL /* comments */,
1072 NULL /* keywords */,
1073 NULL /* optional field */);
1074 if (field == NULL)
1075 goto free;
1076 r = mailimf_fields_add(fields, field);
1077 if (r != MAILIMF_NO_ERROR)
1078 goto free_field;
1079 }
1080
1081 if (references != NULL) {
1082 imf_references = mailimf_references_new(references);
1083 if (imf_references == NULL)
1084 goto free;
1085 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1086 NULL /* return-path */,
1087 NULL /* resent date */,
1088 NULL /* resent from */,
1089 NULL /* resent sender */,
1090 NULL /* resent to */,
1091 NULL /* resent cc */,
1092 NULL /* resent bcc */,
1093 NULL /* resent msg id */,
1094 NULL /* date */,
1095 NULL /* from */,
1096 NULL /* sender */,
1097 NULL /* reply-to */,
1098 NULL /* to */,
1099 NULL /* cc */,
1100 NULL /* bcc */,
1101 NULL /* message id */,
1102 NULL /* in reply to */,
1103 imf_references /* references */,
1104 NULL /* subject */,
1105 NULL /* comments */,
1106 NULL /* keywords */,
1107 NULL /* optional field */);
1108 if (field == NULL)
1109 goto free;
1110 r = mailimf_fields_add(fields, field);
1111 if (r != MAILIMF_NO_ERROR)
1112 goto free_field;
1113 }
1114
1115 if (subject != NULL) {
1116 imf_subject = mailimf_subject_new(subject);
1117 if (imf_subject == NULL)
1118 goto free;
1119 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1120 NULL /* return-path */,
1121 NULL /* resent date */,
1122 NULL /* resent from */,
1123 NULL /* resent sender */,
1124 NULL /* resent to */,
1125 NULL /* resent cc */,
1126 NULL /* resent bcc */,
1127 NULL /* resent msg id */,
1128 NULL /* date */,
1129 NULL /* from */,
1130 NULL /* sender */,
1131 NULL /* reply-to */,
1132 NULL /* to */,
1133 NULL /* cc */,
1134 NULL /* bcc */,
1135 NULL /* message id */,
1136 NULL /* in reply to */,
1137 NULL /* references */,
1138 imf_subject /* subject */,
1139 NULL /* comments */,
1140 NULL /* keywords */,
1141 NULL /* optional field */);
1142 if (field == NULL)
1143 goto free;
1144 r = mailimf_fields_add(fields, field);
1145 if (r != MAILIMF_NO_ERROR)
1146 goto free_field;
1147 }
1148
1149 return MAILIMF_NO_ERROR;
1150
1151 free_field:
1152 if (field != NULL) {
1153 detach_field(field);
1154 mailimf_field_free(field);
1155 }
1156 free:
1157 detach_free_fields(imf_date,
1158 imf_from,
1159 imf_sender,
1160 imf_reply_to,
1161 imf_to,
1162 imf_cc,
1163 imf_bcc,
1164 imf_msg_id,
1165 imf_in_reply_to,
1166 imf_references,
1167 imf_subject);
1168
1169 return MAILIMF_ERROR_MEMORY;
1170}
1171
1172struct mailimf_fields *
1173mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
1174 struct mailimf_mailbox_list * from,
1175 struct mailimf_mailbox * sender,
1176 struct mailimf_address_list * reply_to,
1177 struct mailimf_address_list * to,
1178 struct mailimf_address_list * cc,
1179 struct mailimf_address_list * bcc,
1180 char * message_id,
1181 clist * in_reply_to,
1182 clist * references,
1183 char * subject)
1184{
1185 struct mailimf_fields * fields;
1186 int r;
1187
1188 fields = mailimf_fields_new_empty();
1189 if (fields == NULL)
1190 goto err;
1191
1192 r = mailimf_fields_add_data(fields,
1193 date,
1194 from,
1195 sender,
1196 reply_to,
1197 to,
1198 cc,
1199 bcc,
1200 message_id,
1201 in_reply_to,
1202 references,
1203 subject);
1204 if (r != MAILIMF_NO_ERROR)
1205 goto free;
1206
1207 return fields;
1208
1209 free:
1210 mailimf_fields_free(fields);
1211 err:
1212 return NULL;
1213}
1214
1215struct mailimf_fields *
1216mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
1217 struct mailimf_mailbox * sender,
1218 struct mailimf_address_list * reply_to,
1219 struct mailimf_address_list * to,
1220 struct mailimf_address_list * cc,
1221 struct mailimf_address_list * bcc,
1222 clist * in_reply_to,
1223 clist * references,
1224 char * subject)
1225{
1226 struct mailimf_date_time * date;
1227 char * msg_id;
1228 struct mailimf_fields * fields;
1229
1230 date = mailimf_get_current_date();
1231 if (date == NULL)
1232 goto err;
1233
1234 msg_id = mailimf_get_message_id();
1235 if (msg_id == NULL)
1236 goto free_date;
1237
1238 fields = mailimf_fields_new_with_data_all(date,
1239 from, sender, reply_to,
1240 to, cc, bcc,
1241 msg_id,
1242 in_reply_to, references,
1243 subject);
1244 if (fields == NULL)
1245 goto free_msg_id;
1246
1247 return fields;
1248
1249 free_msg_id:
1250 free(msg_id);
1251 free_date:
1252 mailimf_date_time_free(date);
1253 err:
1254 return NULL;
1255}
1256
1257
1258
1259#define MAX_MESSAGE_ID 512
1260
1261char * mailimf_get_message_id(void)
1262{
1263 char id[MAX_MESSAGE_ID];
1264 time_t now;
1265 char name[MAX_MESSAGE_ID];
1266 long value;
1267
1268 now = time(NULL);
1269 value = random();
1270
1271 gethostname(name, MAX_MESSAGE_ID);
1272 snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s",
1273 now, value, getpid(), name);
1274
1275 return strdup(id);
1276}
1277
1278
1279
1280static time_t mkgmtime(struct tm * tmp);
1281
1282
1283struct mailimf_date_time * mailimf_get_current_date(void)
1284{
1285 struct tm gmt;
1286 struct tm lt;
1287 int off;
1288 time_t now;
1289 struct mailimf_date_time * date_time;
1290
1291 now = time(NULL);
1292
1293 if (gmtime_r(&now, &gmt) == NULL)
1294 return NULL;
1295
1296 if (localtime_r(&now, &lt) == NULL)
1297 return NULL;
1298
1299 off = (mkgmtime(&lt) - mkgmtime(&gmt)) / (60 * 60) * 100;
1300
1301 date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900,
1302 lt.tm_hour, lt.tm_min, lt.tm_sec,
1303 off);
1304
1305 return date_time;
1306}
1307
1308
1309
1310/* mkgmtime.c - make time corresponding to a GMT timeval struct
1311 $Id$
1312
1313 * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
1314 *
1315 * Redistribution and use in source and binary forms, with or without
1316 * modification, are permitted provided that the following conditions
1317 * are met:
1318 *
1319 * 1. Redistributions of source code must retain the above copyright
1320 * notice, this list of conditions and the following disclaimer.
1321 *
1322 * 2. Redistributions in binary form must reproduce the above copyright
1323 * notice, this list of conditions and the following disclaimer in
1324 * the documentation and/or other materials provided with the
1325 * distribution.
1326 *
1327 * 3. The name "Carnegie Mellon University" must not be used to
1328 * endorse or promote products derived from this software without
1329 * prior written permission. For permission or any other legal
1330 * details, please contact
1331 * Office of Technology Transfer
1332 * Carnegie Mellon University
1333 * 5000 Forbes Avenue
1334 * Pittsburgh, PA 15213-3890
1335 * (412) 268-4387, fax: (412) 268-7395
1336 * tech-transfer@andrew.cmu.edu
1337 *
1338 * 4. Redistributions of any form whatsoever must retain the following
1339 * acknowledgment:
1340 * "This product includes software developed by Computing Services
1341 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
1342 *
1343 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
1344 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1345 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
1346 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1347 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
1348 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1349 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1350 *
1351 *
1352 */
1353/*
1354 * Copyright (c) 1987, 1989, 1993
1355 *The Regents of the University of California. All rights reserved.
1356 *
1357 * This code is derived from software contributed to Berkeley by
1358 * Arthur David Olson of the National Cancer Institute.
1359 *
1360 * Redistribution and use in source and binary forms, with or without
1361 * modification, are permitted provided that the following conditions
1362 * are met:
1363 * 1. Redistributions of source code must retain the above copyright
1364 * notice, this list of conditions and the following disclaimer.
1365 * 2. Redistributions in binary form must reproduce the above copyright
1366 * notice, this list of conditions and the following disclaimer in the
1367 * documentation and/or other materials provided with the distribution.
1368 * 3. All advertising materials mentioning features or use of this software
1369 * must display the following acknowledgement:
1370 *This product includes software developed by the University of
1371 *California, Berkeley and its contributors.
1372 * 4. Neither the name of the University nor the names of its contributors
1373 * may be used to endorse or promote products derived from this software
1374 * without specific prior written permission.
1375 *
1376 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1377 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1378 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1379 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1380 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1381 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1382 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1383 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1384 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1385 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1386 * SUCH DAMAGE.
1387 */
1388
1389/*
1390** Adapted from code provided by Robert Elz, who writes:
1391 **The "best" way to do mktime I think is based on an idea of Bob
1392 **Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1393 **It does a binary search of the time_t space. Since time_t's are
1394 **just 32 bits, its a max of 32 iterations (even at 64 bits it
1395 **would still be very reasonable).
1396*/
1397
1398/*
1399 adapted for libEtPan! by DINH V. Hoa
1400*/
1401
1402#ifndef WRONG
1403 #define WRONG(-1)
1404#endif /* !defined WRONG */
1405
1406static int tmcomp(struct tm * atmp, struct tm * btmp)
1407{
1408 register intresult;
1409
1410 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1411 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1412 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1413 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1414 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1415 result = atmp->tm_sec - btmp->tm_sec;
1416 return result;
1417}
1418
1419static time_t mkgmtime(struct tm * tmp)
1420{
1421 register int dir;
1422 register int bits;
1423 register int saved_seconds;
1424 time_t t;
1425 struct tm yourtm, *mytm;
1426
1427 yourtm = *tmp;
1428 saved_seconds = yourtm.tm_sec;
1429 yourtm.tm_sec = 0;
1430 /*
1431 ** Calculate the number of magnitude bits in a time_t
1432 ** (this works regardless of whether time_t is
1433 ** signed or unsigned, though lint complains if unsigned).
1434 */
1435 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1436 ;
1437 /*
1438 ** If time_t is signed, then 0 is the median value,
1439 ** if time_t is unsigned, then 1 << bits is median.
1440 */
1441 t = (t < 0) ? 0 : ((time_t) 1 << bits);
1442 for ( ; ; ) {
1443 mytm = gmtime(&t);
1444 dir = tmcomp(mytm, &yourtm);
1445 if (dir != 0) {
1446 if (bits-- < 0)
1447 return WRONG;
1448 if (bits < 0)
1449 --t;
1450 else if (dir > 0)
1451 t -= (time_t) 1 << bits;
1452 elset += (time_t) 1 << bits;
1453 continue;
1454 }
1455 break;
1456 }
1457 t += saved_seconds;
1458 return t;
1459}
1460
1461
1462
1463
1464
1465
1466
1467void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
1468 struct mailimf_fields * fields)
1469{
1470 clistiter * cur;
1471
1472 memset(single_fields, 0, sizeof(struct mailimf_single_fields));
1473
1474 cur = clist_begin(fields->fld_list);
1475 while (cur != NULL) {
1476 struct mailimf_field * field;
1477
1478 field = clist_content(cur);
1479
1480 switch (field->fld_type) {
1481 case MAILIMF_FIELD_ORIG_DATE:
1482 if (single_fields->fld_orig_date == NULL)
1483 single_fields->fld_orig_date = field->fld_data.fld_orig_date;
1484 cur = clist_next(cur);
1485 break;
1486 case MAILIMF_FIELD_FROM:
1487 if (single_fields->fld_from == NULL) {
1488 single_fields->fld_from = field->fld_data.fld_from;
1489 cur = clist_next(cur);
1490 }
1491 else {
1492 clist_concat(single_fields->fld_from->frm_mb_list->mb_list,
1493 field->fld_data.fld_from->frm_mb_list->mb_list);
1494 mailimf_field_free(field);
1495 cur = clist_delete(fields->fld_list, cur);
1496 }
1497 break;
1498 case MAILIMF_FIELD_SENDER:
1499 if (single_fields->fld_sender == NULL)
1500 single_fields->fld_sender = field->fld_data.fld_sender;
1501 cur = clist_next(cur);
1502 break;
1503 case MAILIMF_FIELD_REPLY_TO:
1504 if (single_fields->fld_reply_to == NULL) {
1505 single_fields->fld_reply_to = field->fld_data.fld_reply_to;
1506 cur = clist_next(cur);
1507 }
1508 else {
1509 clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list,
1510 field->fld_data.fld_reply_to->rt_addr_list->ad_list);
1511 mailimf_field_free(field);
1512 cur = clist_delete(fields->fld_list, cur);
1513 }
1514 break;
1515 case MAILIMF_FIELD_TO:
1516 if (single_fields->fld_to == NULL) {
1517 single_fields->fld_to = field->fld_data.fld_to;
1518 cur = clist_next(cur);
1519 }
1520 else {
1521 clist_concat(single_fields->fld_to->to_addr_list->ad_list,
1522 field->fld_data.fld_to->to_addr_list->ad_list);
1523 mailimf_field_free(field);
1524 cur = clist_delete(fields->fld_list, cur);
1525 }
1526 break;
1527 case MAILIMF_FIELD_CC:
1528 if (single_fields->fld_cc == NULL) {
1529 single_fields->fld_cc = field->fld_data.fld_cc;
1530 cur = clist_next(cur);
1531 }
1532 else {
1533 clist_concat(single_fields->fld_cc->cc_addr_list->ad_list,
1534 field->fld_data.fld_cc->cc_addr_list->ad_list);
1535 mailimf_field_free(field);
1536 cur = clist_delete(fields->fld_list, cur);
1537 }
1538 break;
1539 case MAILIMF_FIELD_BCC:
1540 if (single_fields->fld_bcc == NULL) {
1541 single_fields->fld_bcc = field->fld_data.fld_bcc;
1542 cur = clist_next(cur);
1543 }
1544 else {
1545 clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list,
1546 field->fld_data.fld_bcc->bcc_addr_list->ad_list);
1547 mailimf_field_free(field);
1548 cur = clist_delete(fields->fld_list, cur);
1549 }
1550 break;
1551 case MAILIMF_FIELD_MESSAGE_ID:
1552 if (single_fields->fld_message_id == NULL)
1553 single_fields->fld_message_id = field->fld_data.fld_message_id;
1554 cur = clist_next(cur);
1555 break;
1556 case MAILIMF_FIELD_IN_REPLY_TO:
1557 if (single_fields->fld_in_reply_to == NULL)
1558 single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to;
1559 cur = clist_next(cur);
1560 break;
1561 case MAILIMF_FIELD_REFERENCES:
1562 if (single_fields->fld_references == NULL)
1563 single_fields->fld_references = field->fld_data.fld_references;
1564 cur = clist_next(cur);
1565 break;
1566 case MAILIMF_FIELD_SUBJECT:
1567 if (single_fields->fld_subject == NULL)
1568 single_fields->fld_subject = field->fld_data.fld_subject;
1569 cur = clist_next(cur);
1570 break;
1571 case MAILIMF_FIELD_COMMENTS:
1572 if (single_fields->fld_comments == NULL)
1573 single_fields->fld_comments = field->fld_data.fld_comments;
1574 cur = clist_next(cur);
1575 break;
1576 case MAILIMF_FIELD_KEYWORDS:
1577 if (single_fields->fld_keywords == NULL)
1578 single_fields->fld_keywords = field->fld_data.fld_keywords;
1579 cur = clist_next(cur);
1580 break;
1581 default:
1582 cur = clist_next(cur);
1583 break;
1584 }
1585 }
1586}
1587
1588
1589struct mailimf_single_fields *
1590mailimf_single_fields_new(struct mailimf_fields * fields)
1591{
1592 struct mailimf_single_fields * single_fields;
1593
1594 single_fields = malloc(sizeof(struct mailimf_single_fields));
1595 if (single_fields == NULL)
1596 goto err;
1597
1598 mailimf_single_fields_init(single_fields, fields);
1599
1600 return single_fields;
1601
1602 err:
1603 return NULL;
1604}
1605
1606void mailimf_single_fields_free(struct mailimf_single_fields *
1607 single_fields)
1608{
1609 free(single_fields);
1610}
1611
1612struct mailimf_field * mailimf_field_new_custom(char * name, char * value)
1613{
1614 struct mailimf_optional_field * opt_field;
1615 struct mailimf_field * field;
1616
1617 opt_field = mailimf_optional_field_new(name, value);
1618 if (opt_field == NULL)
1619 goto err;
1620
1621 field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD,
1622 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1623 NULL, NULL, NULL, NULL,
1624 NULL, NULL, NULL, NULL,
1625 NULL, NULL, NULL, NULL,
1626 NULL, NULL, opt_field);
1627 if (field == NULL)
1628 goto free_opt_field;
1629
1630 return field;
1631
1632 free_opt_field:
1633 mailimf_optional_field_free(opt_field);
1634 err:
1635 return NULL;
1636}
diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.h b/libetpan/src/low-level/imf/mailimf_types_helper.h
new file mode 100644
index 0000000..337b1d0
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_types_helper.h
@@ -0,0 +1,370 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_TYPES_HELPER
37
38#define MAILIMF_TYPES_HELPER
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf_types.h>
45
46/*
47 IMPORTANT NOTE:
48
49 All allocation functions will take as argument allocated data
50 and will store these data in the structure they will allocate.
51 Data should be persistant during all the use of the structure
52 and will be freed by the free function of the structure
53
54 allocation functions will return NULL on failure
55*/
56
57/*
58 mailimf_mailbox_list_new_empty creates an empty list of mailboxes
59*/
60
61struct mailimf_mailbox_list *
62mailimf_mailbox_list_new_empty();
63
64/*
65 mailimf_mailbox_list_add adds a mailbox to the list of mailboxes
66
67 @return MAILIMF_NO_ERROR will be returned on success,
68 other code will be returned otherwise
69*/
70
71int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
72 struct mailimf_mailbox * mb);
73
74/*
75 mailimf_mailbox_list_add_parse parse the given string
76 into a mailimf_mailbox structure and adds it to the list of mailboxes
77
78 @return MAILIMF_NO_ERROR will be returned on success,
79 other code will be returned otherwise
80*/
81
82int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
83 char * mb_str);
84
85/*
86 mailimf_mailbox creates a mailimf_mailbox structure with the given
87 arguments and adds it to the list of mailboxes
88
89 - display_name is the name that will be displayed for this mailbox,
90 for example 'name' in '"name" <mailbox@domain>,
91 should be allocated with malloc()
92
93 - address is the mailbox, for example 'mailbox@domain'
94 in '"name" <mailbox@domain>, should be allocated with malloc()
95
96 @return MAILIMF_NO_ERROR will be returned on success,
97 other code will be returned otherwise
98*/
99
100int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
101 char * display_name, char * address);
102
103/*
104 mailimf_address_list_new_empty creates an empty list of addresses
105*/
106
107struct mailimf_address_list *
108mailimf_address_list_new_empty();
109
110/*
111 mailimf_address_list_add adds a mailbox to the list of addresses
112
113 @return MAILIMF_NO_ERROR will be returned on success,
114 other code will be returned otherwise
115*/
116
117int mailimf_address_list_add(struct mailimf_address_list * address_list,
118 struct mailimf_address * addr);
119
120/*
121 mailimf_address_list_add_parse parse the given string
122 into a mailimf_address structure and adds it to the list of addresses
123
124 @return MAILIMF_NO_ERROR will be returned on success,
125 other code will be returned otherwise
126*/
127
128int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
129 char * addr_str);
130
131/*
132 mailimf_address_list_add_mb creates a mailbox mailimf_address
133 with the given arguments and adds it to the list of addresses
134
135 - display_name is the name that will be displayed for this mailbox,
136 for example 'name' in '"name" <mailbox@domain>,
137 should be allocated with malloc()
138
139 - address is the mailbox, for example 'mailbox@domain'
140 in '"name" <mailbox@domain>, should be allocated with malloc()
141
142 @return MAILIMF_NO_ERROR will be returned on success,
143 other code will be returned otherwise
144*/
145
146int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
147 char * display_name, char * address);
148
149/*
150 mailimf_resent_fields_add_data adds a set of resent fields in the
151 given mailimf_fields structure.
152
153 if you don't want a given field in the set to be added in the list
154 of fields, you can give NULL as argument
155
156 @param resent_msg_id sould be allocated with malloc()
157
158 @return MAILIMF_NO_ERROR will be returned on success,
159 other code will be returned otherwise
160*/
161
162int
163mailimf_resent_fields_add_data(struct mailimf_fields * fields,
164 struct mailimf_date_time * resent_date,
165 struct mailimf_mailbox_list * resent_from,
166 struct mailimf_mailbox * resent_sender,
167 struct mailimf_address_list * resent_to,
168 struct mailimf_address_list * resent_cc,
169 struct mailimf_address_list * resent_bcc,
170 char * resent_msg_id);
171
172/*
173 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
174 structure with a set of resent fields
175
176 if you don't want a given field in the set to be added in the list
177 of fields, you can give NULL as argument
178
179 @param resent_msg_id sould be allocated with malloc()
180
181 @return MAILIMF_NO_ERROR will be returned on success,
182 other code will be returned otherwise
183*/
184
185struct mailimf_fields *
186mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
187 resent_date, struct mailimf_mailbox_list * resent_from,
188 struct mailimf_mailbox * resent_sender,
189 struct mailimf_address_list * resent_to,
190 struct mailimf_address_list * resent_cc,
191 struct mailimf_address_list * resent_bcc,
192 char * resent_msg_id);
193
194/*
195 mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
196 structure with a set of resent fields.
197 Resent-Date and Resent-Message-ID fields will be generated for you.
198
199 if you don't want a given field in the set to be added in the list
200 of fields, you can give NULL as argument
201
202 @return MAILIMF_NO_ERROR will be returned on success,
203 other code will be returned otherwise
204*/
205
206struct mailimf_fields *
207mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
208 struct mailimf_mailbox * sender,
209 struct mailimf_address_list * to,
210 struct mailimf_address_list * cc,
211 struct mailimf_address_list * bcc);
212
213/*
214 this function creates a new mailimf_fields structure with no fields
215*/
216
217struct mailimf_fields *
218mailimf_fields_new_empty(void);
219
220
221/*
222 this function adds a field to the mailimf_fields structure
223
224 @return MAILIMF_NO_ERROR will be returned on success,
225 other code will be returned otherwise
226*/
227
228int mailimf_fields_add(struct mailimf_fields * fields,
229 struct mailimf_field * field);
230
231
232/*
233 mailimf_fields_add_data adds a set of fields in the
234 given mailimf_fields structure.
235
236 if you don't want a given field in the set to be added in the list
237 of fields, you can give NULL as argument
238
239 @param msg_id sould be allocated with malloc()
240 @param subject should be allocated with malloc()
241 @param in_reply_to each elements of this list should be allocated
242 with malloc()
243 @param references each elements of this list should be allocated
244 with malloc()
245
246 @return MAILIMF_NO_ERROR will be returned on success,
247 other code will be returned otherwise
248*/
249
250int mailimf_fields_add_data(struct mailimf_fields * fields,
251 struct mailimf_date_time * date,
252 struct mailimf_mailbox_list * from,
253 struct mailimf_mailbox * sender,
254 struct mailimf_address_list * reply_to,
255 struct mailimf_address_list * to,
256 struct mailimf_address_list * cc,
257 struct mailimf_address_list * bcc,
258 char * msg_id,
259 clist * in_reply_to,
260 clist * references,
261 char * subject);
262
263/*
264 mailimf_fields_new_with_data_all creates a new mailimf_fields
265 structure with a set of fields
266
267 if you don't want a given field in the set to be added in the list
268 of fields, you can give NULL as argument
269
270 @param message_id sould be allocated with malloc()
271 @param subject should be allocated with malloc()
272 @param in_reply_to each elements of this list should be allocated
273 with malloc()
274 @param references each elements of this list should be allocated
275 with malloc()
276
277 @return MAILIMF_NO_ERROR will be returned on success,
278 other code will be returned otherwise
279*/
280
281struct mailimf_fields *
282mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
283 struct mailimf_mailbox_list * from,
284 struct mailimf_mailbox * sender,
285 struct mailimf_address_list * reply_to,
286 struct mailimf_address_list * to,
287 struct mailimf_address_list * cc,
288 struct mailimf_address_list * bcc,
289 char * message_id,
290 clist * in_reply_to,
291 clist * references,
292 char * subject);
293
294/*
295 mailimf_fields_new_with_data creates a new mailimf_fields
296 structure with a set of fields
297 Date and Message-ID fields will be generated for you.
298
299 if you don't want a given field in the set to be added in the list
300 of fields, you can give NULL as argument
301
302 @param subject should be allocated with malloc()
303 @param in_reply_to each elements of this list should be allocated
304 with malloc()
305 @param references each elements of this list should be allocated
306 with malloc()
307
308 @return MAILIMF_NO_ERROR will be returned on success,
309 other code will be returned otherwise
310*/
311
312struct mailimf_fields *
313mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
314 struct mailimf_mailbox * sender,
315 struct mailimf_address_list * reply_to,
316 struct mailimf_address_list * to,
317 struct mailimf_address_list * cc,
318 struct mailimf_address_list * bcc,
319 clist * in_reply_to,
320 clist * references,
321 char * subject);
322
323/*
324 this function returns an allocated message identifier to
325 use in a Message-ID or Resent-Message-ID field
326*/
327
328char * mailimf_get_message_id(void);
329
330/*
331 this function returns a mailimf_date_time structure to
332 use in a Date or Resent-Date field
333*/
334
335struct mailimf_date_time * mailimf_get_current_date(void);
336
337
338/*
339 mailimf_single_fields_init fills a mailimf_single_fields structure
340 with the content of a mailimf_fields structure
341*/
342
343void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
344 struct mailimf_fields * fields);
345
346/*
347 mailimf_single_fields_new creates a new mailimf_single_fields and
348 fills the structure with mailimf_fields
349*/
350
351struct mailimf_single_fields *
352mailimf_single_fields_new(struct mailimf_fields * fields);
353
354void mailimf_single_fields_free(struct mailimf_single_fields *
355 single_fields);
356
357/*
358 mailimf_field_new_custom creates a new field of type optional
359
360 @param name should be allocated with malloc()
361 @param value should be allocated with malloc()
362*/
363
364struct mailimf_field * mailimf_field_new_custom(char * name, char * value);
365
366#ifdef __cplusplus
367}
368#endif
369
370#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write.c b/libetpan/src/low-level/imf/mailimf_write.c
new file mode 100644
index 0000000..7301f37
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write.c
@@ -0,0 +1,2021 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf_write.h"
37
38#include <time.h>
39#include <string.h>
40#include <ctype.h>
41
42#define MAX_MAIL_COL 72
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#define MAX_VALID_IMF_LINE 998
53
54static int mailimf_orig_date_write(FILE * f, int * col,
55 struct mailimf_orig_date * date);
56static int mailimf_date_time_write(FILE * f, int * col,
57 struct mailimf_date_time * date_time);
58static int mailimf_from_write(FILE * f, int * col,
59 struct mailimf_from * from);
60static int mailimf_sender_write(FILE * f, int * col,
61 struct mailimf_sender * sender);
62static int mailimf_reply_to_write(FILE * f, int * col,
63 struct mailimf_reply_to * reply_to);
64static int mailimf_to_write(FILE * f, int * col,
65 struct mailimf_to * to);
66static int mailimf_cc_write(FILE * f, int * col,
67 struct mailimf_cc * to);
68static int mailimf_bcc_write(FILE * f, int * col,
69 struct mailimf_bcc * to);
70static int mailimf_message_id_write(FILE * f, int * col,
71 struct mailimf_message_id * message_id);
72static int mailimf_msg_id_list_write(FILE * f, int * col,
73 clist * list);
74static int mailimf_in_reply_to_write(FILE * f, int * col,
75 struct mailimf_in_reply_to *
76 in_reply_to);
77static int mailimf_references_write(FILE * f, int * col,
78 struct mailimf_references * references);
79static int mailimf_subject_write(FILE * f, int * col,
80 struct mailimf_subject * subject);
81
82static int mailimf_address_write(FILE * f, int * col,
83 struct mailimf_address * addr);
84static int mailimf_group_write(FILE * f, int * col,
85 struct mailimf_group * group);
86
87static int mailimf_mailbox_write(FILE * f, int * col,
88 struct mailimf_mailbox * mb);
89
90static int mailimf_comments_write(FILE * f, int * col,
91 struct mailimf_comments * comments);
92
93static int mailimf_optional_field_write(FILE * f, int * col,
94 struct mailimf_optional_field * field);
95
96static int mailimf_keywords_write(FILE * f, int * col,
97 struct mailimf_keywords * keywords);
98
99static int mailimf_return_write(FILE * f, int * col,
100 struct mailimf_return * return_path);
101
102static int mailimf_path_write(FILE * f, int * col,
103 struct mailimf_path * path);
104
105static int mailimf_resent_date_write(FILE * f, int * col,
106 struct mailimf_orig_date * date);
107
108static int mailimf_resent_from_write(FILE * f, int * col,
109 struct mailimf_from * from);
110
111static int mailimf_resent_sender_write(FILE * f, int * col,
112 struct mailimf_sender * sender);
113
114static int mailimf_resent_to_write(FILE * f, int * col,
115 struct mailimf_to * to);
116
117static int mailimf_resent_cc_write(FILE * f, int * col,
118 struct mailimf_cc * cc);
119
120static int mailimf_resent_bcc_write(FILE * f, int * col,
121 struct mailimf_bcc * bcc);
122
123static int
124mailimf_resent_msg_id_write(FILE * f, int * col,
125 struct mailimf_message_id * message_id);
126
127
128
129/* ************************ */
130
131#if 0
132int mailimf_string_write(FILE * f, int * col,
133 char * str, size_t length)
134{
135 int r;
136
137 if (length != 0) {
138 r = fwrite(str, sizeof(char), length, f);
139 if (r < 0)
140 return MAILIMF_ERROR_FILE;
141 * col += length;
142 }
143
144 return MAILIMF_NO_ERROR;
145}
146#endif
147
148#define CRLF "\r\n"
149#define HEADER_FOLD "\r\n "
150
151static inline int flush_buf(FILE * f, const char * str, size_t length)
152{
153 if (length != 0) {
154 int r;
155
156 r = fwrite(str, 1, length, f);
157 if (r == 0)
158 return MAILIMF_ERROR_FILE;
159 }
160 return MAILIMF_NO_ERROR;
161}
162
163#define CUT_AT_MAX_VALID_IMF_LINE
164
165int mailimf_string_write(FILE * f, int * col,
166 const char * str, size_t length)
167{
168 int r;
169 size_t count;
170 const char * block_begin;
171 const char * p;
172 int done;
173
174 p = str;
175 block_begin = str;
176 count = 0;
177
178 while (length > 0) {
179#ifdef CUT_AT_MAX_VALID_IMF_LINE
180 if (count >= 998) {
181 /*
182 cut lines at maximum valid length for internet message
183 format standard (currently RFC 2822)
184
185 This should not happen.
186 In case there are some lines larger than 998 in body,
187 the encoding must be changed into base64 or quoted-printable
188 so that wrapping to 72 columns is done.
189 */
190
191 r = flush_buf(f, block_begin, count);
192 if (r != MAILIMF_NO_ERROR)
193 return r;
194
195 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
196 if (r == 0)
197 return MAILIMF_ERROR_FILE;
198
199 count = 0;
200 block_begin = p;
201
202 * col = 0;
203 }
204#endif
205 switch (* p) {
206 case '\n':
207 r = flush_buf(f, block_begin, count);
208 if (r != MAILIMF_NO_ERROR)
209 return r;
210
211 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
212 if (r == 0)
213 return MAILIMF_ERROR_FILE;
214
215 p ++;
216 length --;
217 count = 0;
218 block_begin = p;
219
220 * col = 0;
221 break;
222
223 case '\r':
224 done = 0;
225 if (length >= 2) {
226 if (* (p + 1) == '\n') {
227 r = flush_buf(f, block_begin, count);
228 if (r != MAILIMF_NO_ERROR)
229 return r;
230
231 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
232 if (r == 0)
233 return MAILIMF_ERROR_FILE;
234
235 p += 2;
236 length -= 2;
237 count = 0;
238 block_begin = p;
239
240 * col = 0;
241
242 done = 1;
243 }
244 }
245 if (!done) {
246 r = flush_buf(f, block_begin, count);
247 if (r != MAILIMF_NO_ERROR)
248 return r;
249
250 r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f);
251 if (r == 0)
252 return MAILIMF_ERROR_FILE;
253
254 p ++;
255 length --;
256 count = 0;
257 block_begin = p;
258
259 * col = 0;
260 }
261 break;
262
263 default:
264 p ++;
265 count ++;
266 length --;
267 break;
268 }
269 }
270
271 r = flush_buf(f, block_begin, count);
272 if (r != MAILIMF_NO_ERROR)
273 return r;
274 * col += count;
275
276 return MAILIMF_NO_ERROR;
277}
278
279#if 0
280int mailimf_header_string_write(FILE * f, int * col,
281 char * str, size_t length)
282{
283 char * p;
284 char * block_begin;
285 int current_col;
286 char * last_cut;
287 int r;
288 int first;
289
290 if (* col + length < MAX_MAIL_COL)
291 return mailimf_string_write(f, col, str, length);
292
293 first = 1;
294 p = str;
295 block_begin = p;
296 last_cut = block_begin;
297 current_col = * col;
298
299 while (1) {
300 if (current_col >= MAX_MAIL_COL) {
301 /* if we reach the maximum recommanded size of line */
302 if (last_cut == block_begin) {
303 /* if we could not find any place to cut */
304 if (first) {
305 /* fold the header */
306 r = mailimf_string_write(f, col, HEADER_FOLD,
307 sizeof(HEADER_FOLD) - 1);
308 if (r != MAILIMF_NO_ERROR)
309 return r;
310 current_col = * col + p - block_begin;
311 first = 0;
312 }
313 else {
314 /* cut the header */
315 r = mailimf_string_write(f, col, block_begin, p - block_begin);
316 if (r != MAILIMF_NO_ERROR)
317 return r;
318 r = mailimf_string_write(f, col, HEADER_FOLD,
319 sizeof(HEADER_FOLD) - 1);
320 if (r != MAILIMF_NO_ERROR)
321 return r;
322 first = 0;
323 block_begin = p;
324 last_cut = block_begin;
325 current_col = * col + p - block_begin;
326 }
327 }
328 else {
329 /* if we found a place to cut */
330 r = mailimf_string_write(f, col, block_begin, last_cut - block_begin);
331 if (r != MAILIMF_NO_ERROR)
332 return r;
333 r = mailimf_string_write(f, col, HEADER_FOLD,
334 sizeof(HEADER_FOLD) - 1);
335 if (r != MAILIMF_NO_ERROR)
336 return r;
337 first = 0;
338 block_begin = last_cut;
339 last_cut = block_begin;
340 current_col = * col + p - block_begin;
341 continue;
342 }
343 }
344 else {
345 if (length == 0)
346 break;
347
348 switch (* p) {
349 case ' ':
350 case '\t':
351 last_cut = p;
352 current_col ++;
353 break;
354
355 case '\r':
356 case '\n':
357 current_col = 0;
358 break;
359
360 default:
361 current_col ++;
362 break;
363 }
364
365 p ++;
366 length --;
367 }
368 }
369
370 return mailimf_string_write(f, col, block_begin, p - block_begin);
371}
372#endif
373
374#if 0
375enum {
376 STATE_LOWER_72,
377 STATE_LOWER_72_CUT,
378 STATE_EQUAL_72,
379 STATE_LOWER_998,
380 STATE_EQUAL_998,
381};
382
383int mailimf_header_string_write(FILE * f, int * col,
384 const char * str, size_t length)
385{
386 int state;
387 const char * p;
388 const char * block_begin;
389 size_t size;
390 const char * cut;
391 int r;
392
393 if (* col < MAX_MAIL_COL)
394 state = STATE_LOWER_72_CUT;
395 else if (* col == MAX_MAIL_COL)
396 state = STATE_EQUAL_72;
397 else if (* col < MAX_VALID_IMF_LINE)
398 state = STATE_LOWER_998;
399 else
400 state = STATE_EQUAL_998;
401
402 p = str;
403 block_begin = p;
404 size = * col;
405 cut = p;
406
407 while (length > 0) {
408 switch (state) {
409 case STATE_LOWER_72:
410 switch (* p) {
411 case '\r':
412 case '\n':
413 p ++;
414 length --;
415 size = 0;
416 break;
417
418 case ' ':
419 case '\t':
420 cut = p;
421 p ++;
422 length --;
423 size ++;
424 state = STATE_LOWER_72_CUT;
425 break;
426
427 default:
428 if (size < MAX_MAIL_COL - 1) {
429 p ++;
430 length --;
431 size ++;
432 }
433 else {
434 state = STATE_EQUAL_72;
435 p ++;
436 length --;
437 size ++;
438 }
439 break;
440 }
441 break; /* end of STATE_LOWER_72 */
442
443 case STATE_LOWER_72_CUT:
444 switch (* p) {
445 case '\r':
446 case '\n':
447 p ++;
448 length --;
449 size = 0;
450 state = STATE_LOWER_72;
451 break;
452
453 case ' ':
454 case '\t':
455 cut = p;
456 p ++;
457 length --;
458 size ++;
459 break;
460
461 default:
462 if (size < MAX_MAIL_COL) {
463 p ++;
464 length --;
465 size ++;
466 }
467 else {
468 r = mailimf_string_write(f, col, block_begin, cut - block_begin);
469 if (r != MAILIMF_NO_ERROR)
470 return r;
471 r = mailimf_string_write(f, col, HEADER_FOLD,
472 sizeof(HEADER_FOLD) - 1);
473 if (r != MAILIMF_NO_ERROR)
474 return r;
475 p ++;
476 length --;
477 block_begin = cut;
478 if ((* block_begin == ' ') || (* block_begin == '\t'))
479 block_begin ++;
480 size = p - block_begin + * col;
481 state = STATE_LOWER_72;
482 }
483 break;
484 }
485 break; /* end of STATE_LOWER_72_CUT */
486
487 case STATE_EQUAL_72:
488 switch (* p) {
489 case '\r':
490 case '\n':
491 p ++;
492 length --;
493 size = 0;
494 state = STATE_LOWER_72;
495 break;
496
497 case ' ':
498 case '\t':
499 r = mailimf_string_write(f, col, block_begin, p - block_begin);
500 if (r != MAILIMF_NO_ERROR)
501 return r;
502 r = mailimf_string_write(f, col, HEADER_FOLD,
503 sizeof(HEADER_FOLD) - 1);
504 if (r != MAILIMF_NO_ERROR)
505 return r;
506 p ++;
507 length --;
508 block_begin = p;
509 size = p - block_begin + * col;
510 state = STATE_LOWER_72;
511 break;
512
513 default:
514 p ++;
515 length --;
516 size ++;
517 state = STATE_LOWER_998;
518 break;
519 }
520 break; /* end of STATE_EQUAL_72 */
521
522 case STATE_LOWER_998:
523 switch (* p) {
524 case '\r':
525 case '\n':
526 p ++;
527 length --;
528 size = 0;
529 state = STATE_LOWER_72;
530 break;
531
532 case ' ':
533 case '\t':
534 r = mailimf_string_write(f, col, block_begin, p - block_begin);
535 if (r != MAILIMF_NO_ERROR)
536 return r;
537 r = mailimf_string_write(f, col, HEADER_FOLD,
538 sizeof(HEADER_FOLD) - 1);
539 if (r != MAILIMF_NO_ERROR)
540 return r;
541 p ++;
542 length --;
543 block_begin = p;
544 size = p - block_begin + * col;
545 state = STATE_LOWER_72;
546 break;
547
548 default:
549 if (size < MAX_VALID_IMF_LINE - 1) {
550 p ++;
551 length --;
552 size ++;
553 }
554 else {
555 p ++;
556 length --;
557 size = 0;
558 state = STATE_EQUAL_998;
559 }
560 break;
561 }
562 break; /* end of STATE_LOWER_998 */
563
564 case STATE_EQUAL_998:
565 switch (* p) {
566 case '\r':
567 case '\n':
568 p ++;
569 length --;
570 size = 0;
571 state = STATE_LOWER_72;
572 break;
573
574 case ' ':
575 case '\t':
576 r = mailimf_string_write(f, col, block_begin, p - block_begin);
577 if (r != MAILIMF_NO_ERROR)
578 return r;
579 r = mailimf_string_write(f, col, HEADER_FOLD,
580 sizeof(HEADER_FOLD) - 1);
581 if (r != MAILIMF_NO_ERROR)
582 return r;
583 p ++;
584 length --;
585 block_begin = p;
586 size = p - block_begin + * col;
587 state = STATE_LOWER_72;
588 break;
589
590 default:
591#ifdef CUT_AT_MAX_VALID_IMF_LINE
592 r = mailimf_string_write(f, col, block_begin, p - block_begin);
593 if (r != MAILIMF_NO_ERROR)
594 return r;
595 r = mailimf_string_write(f, col, HEADER_FOLD,
596 sizeof(HEADER_FOLD) - 1);
597 if (r != MAILIMF_NO_ERROR)
598 return r;
599 p ++;
600 length --;
601 block_begin = p;
602 size = p - block_begin + * col;
603 state = STATE_LOWER_72;
604#else
605 p ++;
606 length --;
607 size ++;
608#endif
609 break;
610 }
611 break; /* end of STATE_EQUAL_998 */
612 }
613 }
614
615 r = mailimf_string_write(f, col, block_begin, p - block_begin);
616 if (r != MAILIMF_NO_ERROR)
617 return r;
618
619 return MAILIMF_NO_ERROR;
620}
621#endif
622
623enum {
624 STATE_BEGIN,
625 STATE_WORD,
626 STATE_SPACE,
627};
628
629int mailimf_header_string_write(FILE * f, int * col,
630 const char * str, size_t length)
631{
632 int state;
633 const char * p;
634 const char * word_begin;
635 const char * word_end;
636 const char * next_word;
637 int first;
638
639 state = STATE_BEGIN;
640
641 p = str;
642 word_begin = p;
643 word_end = p;
644 next_word = p;
645 first = 1;
646
647 while (length > 0) {
648 switch (state) {
649 case STATE_BEGIN:
650 switch (* p) {
651 case '\r':
652 case '\n':
653 case ' ':
654 case '\t':
655 p ++;
656 length --;
657 break;
658
659 default:
660 word_begin = p;
661 state = STATE_WORD;
662 break;
663 }
664 break;
665
666 case STATE_SPACE:
667 switch (* p) {
668 case '\r':
669 case '\n':
670 case ' ':
671 case '\t':
672 p ++;
673 length --;
674 break;
675
676 default:
677 word_begin = p;
678 state = STATE_WORD;
679 break;
680 }
681 break;
682
683 case STATE_WORD:
684 switch (* p) {
685 case '\r':
686 case '\n':
687 case ' ':
688 case '\t':
689 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
690 mailimf_string_write(f, col, HEADER_FOLD,
691 sizeof(HEADER_FOLD) - 1);
692 else {
693 if (!first)
694 mailimf_string_write(f, col, " ", 1);
695 }
696 first = 0;
697 mailimf_string_write(f, col, word_begin, p - word_begin);
698 state = STATE_SPACE;
699 break;
700
701 default:
702 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
703 mailimf_string_write(f, col, word_begin, p - word_begin);
704 mailimf_string_write(f, col, HEADER_FOLD,
705 sizeof(HEADER_FOLD) - 1);
706 word_begin = p;
707 }
708 p ++;
709 length --;
710 break;
711 }
712 break;
713 }
714 }
715
716 if (state == STATE_WORD) {
717 if (p - word_begin + (* col) >= MAX_MAIL_COL)
718 mailimf_string_write(f, col, HEADER_FOLD,
719 sizeof(HEADER_FOLD) - 1);
720 else {
721 if (!first)
722 mailimf_string_write(f, col, " ", 1);
723 }
724 first = 0;
725 mailimf_string_write(f, col, word_begin, p - word_begin);
726 }
727
728 return MAILIMF_NO_ERROR;
729}
730
731int mailimf_envelope_fields_write(FILE * f, int * col,
732 struct mailimf_fields * fields)
733{
734 clistiter * cur;
735
736 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
737 cur = clist_next(cur)) {
738 int r;
739 struct mailimf_field * field;
740
741 field = clist_content(cur);
742 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
743 r = mailimf_field_write(f, col, field);
744 if (r != MAILIMF_NO_ERROR)
745 return r;
746 }
747 }
748
749 return MAILIMF_NO_ERROR;
750}
751
752int mailimf_fields_write(FILE * f, int * col,
753 struct mailimf_fields * fields)
754{
755 clistiter * cur;
756
757 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
758 cur = clist_next(cur)) {
759 int r;
760
761 r = mailimf_field_write(f, col, clist_content(cur));
762 if (r != MAILIMF_NO_ERROR)
763 return r;
764 }
765
766 return MAILIMF_NO_ERROR;
767}
768
769#if 0
770int mailimf_unparsed_fields_write(FILE * f, int * col,
771 struct mailimf_unparsed_fields * fields)
772{
773 clistiter * cur;
774
775 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
776 int r;
777
778 r = mailimf_optional_field_write(f, col, cur->data);
779 if (r != MAILIMF_NO_ERROR)
780 return r;
781 }
782
783 return MAILIMF_NO_ERROR;
784}
785#endif
786
787int mailimf_field_write(FILE * f, int * col,
788 struct mailimf_field * field)
789{
790 int r;
791
792 switch (field->fld_type) {
793 case MAILIMF_FIELD_RETURN_PATH:
794 r = mailimf_return_write(f, col, field->fld_data.fld_return_path);
795 break;
796 case MAILIMF_FIELD_RESENT_DATE:
797 r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date);
798 break;
799 case MAILIMF_FIELD_RESENT_FROM:
800 r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from);
801 break;
802 case MAILIMF_FIELD_RESENT_SENDER:
803 r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender);
804 break;
805 case MAILIMF_FIELD_RESENT_TO:
806 r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to);
807 break;
808 case MAILIMF_FIELD_RESENT_CC:
809 r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc);
810 break;
811 case MAILIMF_FIELD_RESENT_BCC:
812 r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc);
813 break;
814 case MAILIMF_FIELD_RESENT_MSG_ID:
815 r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id);
816 break;
817 case MAILIMF_FIELD_ORIG_DATE:
818 r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date);
819 break;
820 case MAILIMF_FIELD_FROM:
821 r = mailimf_from_write(f, col, field->fld_data.fld_from);
822 break;
823 case MAILIMF_FIELD_SENDER:
824 r = mailimf_sender_write(f, col, field->fld_data.fld_sender);
825 break;
826 case MAILIMF_FIELD_REPLY_TO:
827 r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to);
828 break;
829 case MAILIMF_FIELD_TO:
830 r = mailimf_to_write(f, col, field->fld_data.fld_to);
831 break;
832 case MAILIMF_FIELD_CC:
833 r = mailimf_cc_write(f, col, field->fld_data.fld_cc);
834 break;
835 case MAILIMF_FIELD_BCC:
836 r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc);
837 break;
838 case MAILIMF_FIELD_MESSAGE_ID:
839 r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id);
840 break;
841 case MAILIMF_FIELD_IN_REPLY_TO:
842 r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to);
843 break;
844 case MAILIMF_FIELD_REFERENCES:
845 r = mailimf_references_write(f, col, field->fld_data.fld_references);
846 break;
847 case MAILIMF_FIELD_SUBJECT:
848 r = mailimf_subject_write(f, col, field->fld_data.fld_subject);
849 break;
850 case MAILIMF_FIELD_COMMENTS:
851 r = mailimf_comments_write(f, col, field->fld_data.fld_comments);
852 break;
853 case MAILIMF_FIELD_KEYWORDS:
854 r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords);
855 break;
856 case MAILIMF_FIELD_OPTIONAL_FIELD:
857 r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field);
858 break;
859 default:
860 r = MAILIMF_ERROR_INVAL;
861 break;
862 }
863
864 if (r != MAILIMF_NO_ERROR)
865 return r;
866
867 return MAILIMF_NO_ERROR;
868}
869
870
871static int mailimf_orig_date_write(FILE * f, int * col,
872 struct mailimf_orig_date * date)
873{
874 int r;
875
876 r = mailimf_string_write(f, col, "Date: ", 6);
877 if (r != MAILIMF_NO_ERROR)
878 return r;
879
880 r = mailimf_date_time_write(f, col, date->dt_date_time);
881 if (r != MAILIMF_NO_ERROR)
882 return r;
883
884 r = mailimf_string_write(f, col, "\r\n", 2);
885 if (r != MAILIMF_NO_ERROR)
886 return r;
887#if 0
888 * col = 0;
889#endif
890
891 return MAILIMF_NO_ERROR;
892}
893
894#define MAX_DATE_STR 256
895
896/* 0 = Sunday */
897/* y > 1752 */
898
899static int dayofweek(int year, int month, int day)
900{
901 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
902
903 year -= month < 3;
904
905 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
906}
907
908static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
909 "Fri", "Sat"};
910static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
911 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
912
913static int mailimf_date_time_write(FILE * f, int * col,
914 struct mailimf_date_time * date_time)
915{
916 int r;
917 char date_str[MAX_DATE_STR];
918#if 0
919 struct tm tmval;
920 time_t timeval;
921#endif
922 int wday;
923
924#if 0
925 tmval.tm_sec = date_time->sec;
926 tmval.tm_min = date_time->min;
927 tmval.tm_hour = date_time->hour;
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_mday = date_time->day;
930 tmval.tm_mon = date_time->month - 1;
931 tmval.tm_year = date_time->year - 1900;
932 tmval.tm_isdst = 1;
933
934 timeval = mktime(&tmval);
935
936 localtime_r(&timeval, &tmval);
937#endif
938
939 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
940
941 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
942 week_of_day_str[wday], date_time->dt_day,
943 month_str[date_time->dt_month - 1],
944 date_time->dt_year, date_time->dt_hour,
945 date_time->dt_min, date_time->dt_sec,
946 date_time->dt_zone);
947
948 r = mailimf_string_write(f, col, date_str, strlen(date_str));
949
950 if (r != MAILIMF_NO_ERROR)
951 return r;
952
953 return MAILIMF_NO_ERROR;
954}
955
956static int mailimf_from_write(FILE * f, int * col,
957 struct mailimf_from * from)
958{
959 int r;
960
961 r = mailimf_string_write(f, col, "From: ", 6);
962 if (r != MAILIMF_NO_ERROR)
963 return r;
964
965 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
966 if (r != MAILIMF_NO_ERROR)
967 return r;
968
969 r = mailimf_string_write(f, col, "\r\n", 2);
970 if (r != MAILIMF_NO_ERROR)
971 return r;
972#if 0
973 * col = 0;
974#endif
975
976 return MAILIMF_NO_ERROR;
977}
978
979static int mailimf_sender_write(FILE * f, int * col,
980 struct mailimf_sender * sender)
981{
982 int r;
983
984 r = mailimf_string_write(f, col, "Sender: ", 8);
985 if (r != MAILIMF_NO_ERROR)
986 return r;
987
988 r = mailimf_mailbox_write(f, col, sender->snd_mb);
989 if (r != MAILIMF_NO_ERROR)
990 return r;
991
992 r = mailimf_string_write(f, col, "\r\n", 2);
993 if (r != MAILIMF_NO_ERROR)
994 return r;
995#if 0
996 * col = 0;
997#endif
998
999 return MAILIMF_NO_ERROR;
1000}
1001
1002static int mailimf_reply_to_write(FILE * f, int * col,
1003 struct mailimf_reply_to * reply_to)
1004{
1005 int r;
1006
1007 r = mailimf_string_write(f, col, "Reply-To: ", 10);
1008 if (r != MAILIMF_NO_ERROR)
1009 return r;
1010
1011 r = mailimf_address_list_write(f, col, reply_to->rt_addr_list);
1012 if (r != MAILIMF_NO_ERROR)
1013 return r;
1014
1015 r = mailimf_string_write(f, col, "\r\n", 2);
1016 if (r != MAILIMF_NO_ERROR)
1017 return r;
1018#if 0
1019 * col = 0;
1020#endif
1021
1022 return MAILIMF_NO_ERROR;
1023}
1024
1025
1026static int mailimf_to_write(FILE * f, int * col,
1027 struct mailimf_to * to)
1028{
1029 int r;
1030
1031 r = mailimf_string_write(f, col, "To: ", 4);
1032 if (r != MAILIMF_NO_ERROR)
1033 return r;
1034
1035 r = mailimf_address_list_write(f, col, to->to_addr_list);
1036 if (r != MAILIMF_NO_ERROR)
1037 return r;
1038
1039 r = mailimf_string_write(f, col, "\r\n", 2);
1040 if (r != MAILIMF_NO_ERROR)
1041 return r;
1042#if 0
1043 * col = 0;
1044#endif
1045
1046 return MAILIMF_NO_ERROR;
1047}
1048
1049
1050static int mailimf_cc_write(FILE * f, int * col,
1051 struct mailimf_cc * cc)
1052{
1053 int r;
1054
1055 r = mailimf_string_write(f, col, "Cc: ", 4);
1056 if (r != MAILIMF_NO_ERROR)
1057 return r;
1058
1059 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1060 if (r != MAILIMF_NO_ERROR)
1061 return r;
1062
1063 r = mailimf_string_write(f, col, "\r\n", 2);
1064 if (r != MAILIMF_NO_ERROR)
1065 return r;
1066#if 0
1067 * col = 0;
1068#endif
1069
1070 return MAILIMF_NO_ERROR;
1071}
1072
1073
1074static int mailimf_bcc_write(FILE * f, int * col,
1075 struct mailimf_bcc * bcc)
1076{
1077 int r;
1078
1079 r = mailimf_string_write(f, col, "Bcc: ", 5);
1080 if (r != MAILIMF_NO_ERROR)
1081 return r;
1082
1083 if (bcc->bcc_addr_list != NULL) {
1084 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1085 if (r != MAILIMF_NO_ERROR)
1086 return r;
1087 }
1088
1089 r = mailimf_string_write(f, col, "\r\n", 2);
1090 if (r != MAILIMF_NO_ERROR)
1091 return r;
1092#if 0
1093 * col = 0;
1094#endif
1095
1096 return MAILIMF_NO_ERROR;
1097}
1098
1099
1100static int mailimf_message_id_write(FILE * f, int * col,
1101 struct mailimf_message_id * message_id)
1102{
1103 int r;
1104
1105 r = mailimf_string_write(f, col, "Message-ID: ", 12);
1106 if (r != MAILIMF_NO_ERROR)
1107 return r;
1108
1109 r = mailimf_string_write(f, col, "<", 1);
1110 if (r != MAILIMF_NO_ERROR)
1111 return r;
1112
1113 r = mailimf_string_write(f, col,
1114 message_id->mid_value,
1115 strlen(message_id->mid_value));
1116 if (r != MAILIMF_NO_ERROR)
1117 return r;
1118
1119 r = mailimf_string_write(f, col, ">", 1);
1120 if (r != MAILIMF_NO_ERROR)
1121 return r;
1122
1123 r = mailimf_string_write(f, col, "\r\n", 2);
1124 if (r != MAILIMF_NO_ERROR)
1125 return r;
1126#if 0
1127 * col = 0;
1128#endif
1129
1130 return MAILIMF_NO_ERROR;
1131}
1132
1133
1134static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list)
1135{
1136 clistiter * cur;
1137 int r;
1138 int first;
1139
1140 first = TRUE;
1141
1142 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1143 char * msgid;
1144 size_t len;
1145
1146 msgid = clist_content(cur);
1147 len = strlen(msgid);
1148
1149 /*
1150 XXX - if this is the first message ID, don't fold.
1151 This is a workaround for a bug of old versions of INN.
1152 */
1153 if (!first) {
1154 if (* col > 1) {
1155
1156 if (* col + len >= MAX_MAIL_COL) {
1157 r = mailimf_string_write(f, col, "\r\n ", 3);
1158 if (r != MAILIMF_NO_ERROR)
1159 return r;
1160#if 0
1161 * col = 1;
1162#endif
1163 first = TRUE;
1164 }
1165 }
1166 }
1167
1168 if (!first) {
1169 r = mailimf_string_write(f, col, " ", 1);
1170 if (r != MAILIMF_NO_ERROR)
1171 return r;
1172 }
1173 else {
1174 first = FALSE;
1175 }
1176
1177 r = mailimf_string_write(f, col, "<", 1);
1178 if (r != MAILIMF_NO_ERROR)
1179 return r;
1180
1181 r = mailimf_string_write(f, col, msgid, len);
1182 if (r != MAILIMF_NO_ERROR)
1183 return r;
1184
1185 r = mailimf_string_write(f, col, ">", 1);
1186 if (r != MAILIMF_NO_ERROR)
1187 return r;
1188 }
1189
1190 return MAILIMF_NO_ERROR;
1191}
1192
1193
1194static int mailimf_in_reply_to_write(FILE * f, int * col,
1195 struct mailimf_in_reply_to * in_reply_to)
1196{
1197 int r;
1198
1199 r = mailimf_string_write(f, col, "In-Reply-To: ", 13);
1200 if (r != MAILIMF_NO_ERROR)
1201 return r;
1202
1203 r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list);
1204 if (r != MAILIMF_NO_ERROR)
1205 return r;
1206
1207 r = mailimf_string_write(f, col, "\r\n", 2);
1208 if (r != MAILIMF_NO_ERROR)
1209 return r;
1210#if 0
1211 * col = 0;
1212#endif
1213
1214 return MAILIMF_NO_ERROR;
1215}
1216
1217
1218static int mailimf_references_write(FILE * f, int * col,
1219 struct mailimf_references * references)
1220{
1221 int r;
1222
1223 r = mailimf_string_write(f, col, "References: ", 12);
1224 if (r != MAILIMF_NO_ERROR)
1225 return r;
1226
1227 r = mailimf_msg_id_list_write(f, col, references->mid_list);
1228 if (r != MAILIMF_NO_ERROR)
1229 return r;
1230
1231 r = mailimf_string_write(f, col, "\r\n", 2);
1232 if (r != MAILIMF_NO_ERROR)
1233 return r;
1234#if 0
1235 * col = 0;
1236#endif
1237
1238 return MAILIMF_NO_ERROR;
1239}
1240
1241
1242
1243static int mailimf_subject_write(FILE * f, int * col,
1244 struct mailimf_subject * subject)
1245{
1246 int r;
1247
1248 r = mailimf_string_write(f, col, "Subject: ", 9);
1249 if (r != MAILIMF_NO_ERROR)
1250 return r;
1251
1252 r = mailimf_header_string_write(f, col,
1253 subject->sbj_value, strlen(subject->sbj_value));
1254 if (r != MAILIMF_NO_ERROR)
1255 return r;
1256
1257 r = mailimf_string_write(f, col, "\r\n", 2);
1258 if (r != MAILIMF_NO_ERROR)
1259 return r;
1260#if 0
1261 * col = 0;
1262#endif
1263
1264 return MAILIMF_NO_ERROR;
1265}
1266
1267int mailimf_address_list_write(FILE * f, int * col,
1268 struct mailimf_address_list * addr_list)
1269{
1270 clistiter * cur;
1271 int r;
1272 int first;
1273
1274 first = TRUE;
1275
1276 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1277 cur = clist_next(cur)) {
1278 struct mailimf_address * addr;
1279
1280 addr = clist_content(cur);
1281
1282 if (!first) {
1283 r = mailimf_string_write(f, col, ", ", 2);
1284 if (r != MAILIMF_NO_ERROR)
1285 return r;
1286 }
1287 else {
1288 first = FALSE;
1289 }
1290
1291 r = mailimf_address_write(f, col, addr);
1292 if (r != MAILIMF_NO_ERROR)
1293 return r;
1294 }
1295
1296 return MAILIMF_NO_ERROR;
1297}
1298
1299
1300static int mailimf_address_write(FILE * f, int * col,
1301 struct mailimf_address * addr)
1302{
1303 int r;
1304
1305 switch(addr->ad_type) {
1306 case MAILIMF_ADDRESS_MAILBOX:
1307 r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox);
1308 if (r != MAILIMF_NO_ERROR)
1309 return r;
1310
1311 break;
1312
1313 case MAILIMF_ADDRESS_GROUP:
1314 r = mailimf_group_write(f, col, addr->ad_data.ad_group);
1315 if (r != MAILIMF_NO_ERROR)
1316 return r;
1317
1318 break;
1319 }
1320
1321 return MAILIMF_NO_ERROR;
1322}
1323
1324
1325static int mailimf_group_write(FILE * f, int * col,
1326 struct mailimf_group * group)
1327{
1328 int r;
1329
1330 r = mailimf_header_string_write(f, col, group->grp_display_name,
1331 strlen(group->grp_display_name));
1332 if (r != MAILIMF_NO_ERROR)
1333 return r;
1334
1335 r = mailimf_string_write(f, col, ": ", 2);
1336 if (r != MAILIMF_NO_ERROR)
1337 return r;
1338
1339 if (group->grp_mb_list != NULL) {
1340 r = mailimf_mailbox_list_write(f, col, group->grp_mb_list);
1341 if (r != MAILIMF_NO_ERROR)
1342 return r;
1343 }
1344
1345 r = mailimf_string_write(f, col, ";", 1);
1346 if (r != MAILIMF_NO_ERROR)
1347 return r;
1348
1349 return MAILIMF_NO_ERROR;
1350}
1351
1352
1353int mailimf_mailbox_list_write(FILE * f, int * col,
1354 struct mailimf_mailbox_list * mb_list)
1355{
1356 clistiter * cur;
1357 int r;
1358 int first;
1359
1360 first = TRUE;
1361
1362 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1363 cur = clist_next(cur)) {
1364 struct mailimf_mailbox * mb;
1365
1366 mb = clist_content(cur);
1367
1368 if (!first) {
1369 r = mailimf_string_write(f, col, ", ", 2);
1370 if (r != MAILIMF_NO_ERROR)
1371 return r;
1372 }
1373 else {
1374 first = FALSE;
1375 }
1376
1377 r = mailimf_mailbox_write(f, col, mb);
1378 if (r != MAILIMF_NO_ERROR)
1379 return r;
1380 }
1381
1382 return MAILIMF_NO_ERROR;
1383}
1384
1385
1386int mailimf_quoted_string_write(FILE * f, int * col,
1387 const char * string, size_t len)
1388{
1389 int r;
1390 size_t i;
1391
1392 fputc('\"', f);
1393 for(i = 0 ; i < len ; i ++) {
1394 switch (string[i]) {
1395 case '\\':
1396 case '\"':
1397 r = fputc('\\', f);
1398 if (r < 0)
1399 return MAILIMF_ERROR_FILE;
1400 r = fputc(string[i], f);
1401 if (r < 0)
1402 return MAILIMF_ERROR_FILE;
1403 (* col) += 2;
1404 break;
1405
1406 default:
1407 r = fputc(string[i], f);
1408 if (r < 0)
1409 return MAILIMF_ERROR_FILE;
1410 (* col) ++;
1411 break;
1412 }
1413 }
1414 fputc('\"', f);
1415
1416 return MAILIMF_NO_ERROR;
1417}
1418
1419
1420/*
1421static int
1422atext = ALPHA / DIGIT / ; Any character except controls,
1423 "!" / "#" / ; SP, and specials.
1424 "$" / "%" / ; Used for atoms
1425 "&" / "'" /
1426 "*" / "+" /
1427 "-" / "/" /
1428 "=" / "?" /
1429 "^" / "_" /
1430 "`" / "{" /
1431 "|" / "}" /
1432 "~"
1433*/
1434
1435static int is_atext(const char * s)
1436{
1437 const char * p;
1438
1439 for(p = s ; * p != 0 ; p ++) {
1440 if (isalpha((unsigned char) * p))
1441 continue;
1442 if (isdigit((unsigned char) * p))
1443 continue;
1444 switch (*p) {
1445 case ' ':
1446 case '\t':
1447 case '!':
1448 case '#':
1449 case '$':
1450 case '%':
1451 case '&':
1452 case '\'':
1453 case '*':
1454 case '+':
1455 case '-':
1456 case '/':
1457 case '=':
1458 case '?':
1459 case '^':
1460 case '_':
1461 case '`':
1462 case '{':
1463 case '|':
1464 case '}':
1465 case '~':
1466 break;
1467 default:
1468 return 0;
1469 }
1470 }
1471
1472 return 1;
1473}
1474
1475static int mailimf_mailbox_write(FILE * f, int * col,
1476 struct mailimf_mailbox * mb)
1477{
1478 int r;
1479 int do_fold;
1480
1481#if 0
1482 if (* col > 1) {
1483
1484 if (mb->mb_display_name != NULL) {
1485 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1486 r = mailimf_string_write(f, col, "\r\n ", 3);
1487 if (r != MAILIMF_NO_ERROR)
1488 return r;
1489#if 0
1490 * col = 1;
1491#endif
1492 }
1493 }
1494 }
1495#endif
1496
1497 if (mb->mb_display_name) {
1498
1499 if (is_atext(mb->mb_display_name)) {
1500 r = mailimf_header_string_write(f, col, mb->mb_display_name,
1501 strlen(mb->mb_display_name));
1502 if (r != MAILIMF_NO_ERROR)
1503 return r;
1504 }
1505 else {
1506 if (mb->mb_display_name != NULL) {
1507 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1508 r = mailimf_string_write(f, col, "\r\n ", 3);
1509 if (r != MAILIMF_NO_ERROR)
1510 return r;
1511 }
1512 }
1513
1514 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1515 return MAILIMF_ERROR_INVAL;
1516
1517 r = mailimf_quoted_string_write(f, col, mb->mb_display_name,
1518 strlen(mb->mb_display_name));
1519 if (r != MAILIMF_NO_ERROR)
1520 return r;
1521 }
1522
1523 do_fold = 0;
1524 if (* col > 1) {
1525
1526 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1527 r = mailimf_string_write(f, col, "\r\n ", 3);
1528 if (r != MAILIMF_NO_ERROR)
1529 return r;
1530#if 0
1531 * col = 1;
1532#endif
1533 do_fold = 1;
1534 }
1535 }
1536
1537 if (do_fold)
1538 r = mailimf_string_write(f, col, "<", 1);
1539 else
1540 r = mailimf_string_write(f, col, " <", 2);
1541 if (r != MAILIMF_NO_ERROR)
1542 return r;
1543
1544 r = mailimf_string_write(f, col, mb->mb_addr_spec,
1545 strlen(mb->mb_addr_spec));
1546 if (r != MAILIMF_NO_ERROR)
1547 return r;
1548
1549 r = mailimf_string_write(f, col, ">", 1);
1550 if (r != MAILIMF_NO_ERROR)
1551 return r;
1552 }
1553 else {
1554 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1555 r = mailimf_string_write(f, col, "\r\n ", 3);
1556 if (r != MAILIMF_NO_ERROR)
1557 return r;
1558 }
1559
1560 r = mailimf_string_write(f, col,
1561 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1562 if (r != MAILIMF_NO_ERROR)
1563 return r;
1564 }
1565
1566
1567 return MAILIMF_NO_ERROR;
1568}
1569
1570static int mailimf_comments_write(FILE * f, int * col,
1571 struct mailimf_comments * comments)
1572{
1573 int r;
1574
1575 r = mailimf_string_write(f, col, "Comments: ", 10);
1576 if (r != MAILIMF_NO_ERROR)
1577 return r;
1578
1579 r = mailimf_header_string_write(f, col,
1580 comments->cm_value, strlen(comments->cm_value));
1581 if (r != MAILIMF_NO_ERROR)
1582 return r;
1583
1584 r = mailimf_string_write(f, col, "\r\n", 2);
1585 if (r != MAILIMF_NO_ERROR)
1586 return r;
1587#if 0
1588 * col = 0;
1589#endif
1590
1591 return MAILIMF_NO_ERROR;
1592}
1593
1594static int mailimf_optional_field_write(FILE * f, int * col,
1595 struct mailimf_optional_field * field)
1596{
1597 int r;
1598
1599 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1600 return MAILIMF_ERROR_INVAL;
1601
1602 r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name));
1603 if (r != MAILIMF_NO_ERROR)
1604 return r;
1605
1606 r = mailimf_string_write(f, col, ": ", 2);
1607 if (r != MAILIMF_NO_ERROR)
1608 return r;
1609
1610 r = mailimf_header_string_write(f, col, field->fld_value,
1611 strlen(field->fld_value));
1612 if (r != MAILIMF_NO_ERROR)
1613 return r;
1614
1615#if 0
1616 /* XXX parsing debug */
1617 mailimf_string_write(f, col, " (X)", 4);
1618#endif
1619
1620 r = mailimf_string_write(f, col, "\r\n", 2);
1621 if (r != MAILIMF_NO_ERROR)
1622 return r;
1623#if 0
1624 * col = 0;
1625#endif
1626
1627 return MAILIMF_NO_ERROR;
1628}
1629
1630static int mailimf_keywords_write(FILE * f, int * col,
1631 struct mailimf_keywords * keywords)
1632{
1633 int r;
1634 clistiter * cur;
1635 int first;
1636
1637 r = mailimf_string_write(f, col, "Keywords: ", 10);
1638 if (r != MAILIMF_NO_ERROR)
1639 return r;
1640
1641 first = TRUE;
1642
1643 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1644 cur = clist_next(cur)) {
1645 char * keyword;
1646 size_t len;
1647
1648 keyword = clist_content(cur);
1649 len = strlen(keyword);
1650
1651 if (!first) {
1652 r = mailimf_string_write(f, col, ", ", 2);
1653 if (r != MAILIMF_NO_ERROR)
1654 return r;
1655 }
1656 else {
1657 first = FALSE;
1658 }
1659
1660#if 0
1661 if (* col > 1) {
1662
1663 if (* col + len >= MAX_MAIL_COL) {
1664 r = mailimf_string_write(f, col, "\r\n ", 3);
1665 if (r != MAILIMF_NO_ERROR)
1666 return r;
1667#if 0
1668 * col = 1;
1669#endif
1670 }
1671 }
1672#endif
1673
1674 r = mailimf_header_string_write(f, col, keyword, len);
1675 if (r != MAILIMF_NO_ERROR)
1676 return r;
1677 }
1678
1679 r = mailimf_string_write(f, col, "\r\n", 2);
1680 if (r != MAILIMF_NO_ERROR)
1681 return r;
1682#if 0
1683 * col = 0;
1684#endif
1685
1686 return MAILIMF_NO_ERROR;
1687}
1688
1689#if 0
1690static int mailimf_delivering_info_write(FILE * f, int * col,
1691 struct mailimf_delivering_info * info)
1692{
1693 clistiter * cur;
1694 int r;
1695
1696 for(cur = clist_begin(info->received_fields) ;
1697 cur != NULL ; cur = cur->next) {
1698 struct mailimf_trace_resent_fields * field;
1699
1700 field = cur->data;
1701
1702 r = mailimf_trace_resent_fields_write(f, col, field);
1703 if (r != MAILIMF_NO_ERROR)
1704 return r;
1705 }
1706
1707 return MAILIMF_NO_ERROR;
1708}
1709
1710
1711static int
1712mailimf_trace_resent_fields_write(FILE * f, int * col,
1713 struct mailimf_trace_resent_fields * field)
1714{
1715 int r;
1716
1717 if (field->return_path != NULL) {
1718 r = mailimf_return_write(f, col, field->return_path);
1719 if (r != MAILIMF_NO_ERROR)
1720 return r;
1721 }
1722
1723 if (field->resent_fields != NULL) {
1724 r = mailimf_resent_fields_write(f, col, field->resent_fields);
1725 if (r != MAILIMF_NO_ERROR)
1726 return r;
1727 }
1728
1729 return MAILIMF_NO_ERROR;
1730}
1731#endif
1732
1733static int mailimf_return_write(FILE * f, int * col,
1734 struct mailimf_return * return_path)
1735{
1736 int r;
1737
1738 r = mailimf_string_write(f, col, "Return-Path: ", 13);
1739 if (r != MAILIMF_NO_ERROR)
1740 return r;
1741
1742 r = mailimf_path_write(f, col, return_path->ret_path);
1743 if (r != MAILIMF_NO_ERROR)
1744 return r;
1745
1746 r = mailimf_string_write(f, col, "\r\n", 2);
1747 if (r != MAILIMF_NO_ERROR)
1748 return r;
1749#if 0
1750 * col = 0;
1751#endif
1752
1753 return MAILIMF_NO_ERROR;
1754}
1755
1756static int mailimf_path_write(FILE * f, int * col,
1757 struct mailimf_path * path)
1758{
1759 int r;
1760
1761 r = mailimf_string_write(f, col, "<", 1);
1762 if (r != MAILIMF_NO_ERROR)
1763 return r;
1764
1765 r = mailimf_string_write(f, col, path->pt_addr_spec,
1766 strlen(path->pt_addr_spec));
1767 if (r != MAILIMF_NO_ERROR)
1768 return r;
1769
1770 r = mailimf_string_write(f, col, ">", 1);
1771 if (r != MAILIMF_NO_ERROR)
1772 return r;
1773
1774 return MAILIMF_NO_ERROR;
1775}
1776
1777#if 0
1778static int mailimf_resent_fields_write(FILE * f, int * col,
1779 struct mailimf_resent_fields_list *
1780 resent_fields)
1781{
1782 clistiter * cur;
1783 int r;
1784
1785 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1786 struct mailimf_resent_field * field;
1787
1788 field = cur->data;
1789
1790 r = mailimf_resent_field_write(f, col, field);
1791 if (r != MAILIMF_NO_ERROR)
1792 return r;
1793 }
1794
1795 return MAILIMF_NO_ERROR;
1796}
1797
1798
1799
1800static int mailimf_resent_field_write(FILE * f, int * col,
1801 struct mailimf_resent_field *
1802 resent_field)
1803{
1804 int r;
1805
1806 switch (resent_field->type) {
1807 case MAILIMF_RESENT_FIELD_DATE:
1808 r = mailimf_resent_date_write(f, col, resent_field->resent_date);
1809 break;
1810
1811 case MAILIMF_RESENT_FIELD_FROM:
1812 r = mailimf_resent_from_write(f, col, resent_field->resent_from);
1813 break;
1814
1815 case MAILIMF_RESENT_FIELD_SENDER:
1816 r = mailimf_resent_sender_write(f, col, resent_field->resent_sender);
1817 break;
1818
1819 case MAILIMF_RESENT_FIELD_TO:
1820 r = mailimf_resent_to_write(f, col, resent_field->resent_to);
1821 break;
1822
1823 case MAILIMF_RESENT_FIELD_CC:
1824 r = mailimf_resent_cc_write(f, col, resent_field->resent_cc);
1825 break;
1826
1827 case MAILIMF_RESENT_FIELD_BCC:
1828 r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc);
1829 break;
1830
1831 case MAILIMF_RESENT_FIELD_MSG_ID:
1832 r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id);
1833 break;
1834 default:
1835 r = MAILIMF_ERROR_INVAL;
1836 break;
1837 }
1838
1839
1840 if (r != MAILIMF_NO_ERROR)
1841 return r;
1842
1843 return MAILIMF_NO_ERROR;
1844}
1845#endif
1846
1847static int mailimf_resent_date_write(FILE * f, int * col,
1848 struct mailimf_orig_date * date)
1849{
1850 int r;
1851
1852 r = mailimf_string_write(f, col, "Resent-Date: ", 13);
1853 if (r != MAILIMF_NO_ERROR)
1854 return r;
1855
1856 r = mailimf_date_time_write(f, col, date->dt_date_time);
1857 if (r != MAILIMF_NO_ERROR)
1858 return r;
1859
1860 r = mailimf_string_write(f, col, "\r\n", 2);
1861 if (r != MAILIMF_NO_ERROR)
1862 return r;
1863#if 0
1864 * col = 0;
1865#endif
1866
1867 return MAILIMF_NO_ERROR;
1868}
1869
1870static int mailimf_resent_from_write(FILE * f, int * col,
1871 struct mailimf_from * from)
1872{
1873 int r;
1874
1875 r = mailimf_string_write(f, col, "Resent-From: ", 13);
1876 if (r != MAILIMF_NO_ERROR)
1877 return r;
1878
1879 r = mailimf_mailbox_list_write(f, col, from->frm_mb_list);
1880 if (r != MAILIMF_NO_ERROR)
1881 return r;
1882
1883 r = mailimf_string_write(f, col, "\r\n", 2);
1884 if (r != MAILIMF_NO_ERROR)
1885 return r;
1886#if 0
1887 * col = 0;
1888#endif
1889
1890 return MAILIMF_NO_ERROR;
1891}
1892
1893static int mailimf_resent_sender_write(FILE * f, int * col,
1894 struct mailimf_sender * sender)
1895{
1896 int r;
1897
1898 r = mailimf_string_write(f, col, "Resent-Sender: ", 15);
1899 if (r != MAILIMF_NO_ERROR)
1900 return r;
1901
1902 r = mailimf_mailbox_write(f, col, sender->snd_mb);
1903 if (r != MAILIMF_NO_ERROR)
1904 return r;
1905
1906 r = mailimf_string_write(f, col, "\r\n", 2);
1907 if (r != MAILIMF_NO_ERROR)
1908 return r;
1909#if 0
1910 * col = 0;
1911#endif
1912
1913 return MAILIMF_NO_ERROR;
1914}
1915
1916static int mailimf_resent_to_write(FILE * f, int * col,
1917 struct mailimf_to * to)
1918{
1919 int r;
1920
1921 r = mailimf_string_write(f, col, "Resent-To: ", 11);
1922 if (r != MAILIMF_NO_ERROR)
1923 return r;
1924
1925 r = mailimf_address_list_write(f, col, to->to_addr_list);
1926 if (r != MAILIMF_NO_ERROR)
1927 return r;
1928
1929 r = mailimf_string_write(f, col, "\r\n", 2);
1930 if (r != MAILIMF_NO_ERROR)
1931 return r;
1932#if 0
1933 * col = 0;
1934#endif
1935
1936 return MAILIMF_NO_ERROR;
1937}
1938
1939
1940static int mailimf_resent_cc_write(FILE * f, int * col,
1941 struct mailimf_cc * cc)
1942{
1943 int r;
1944
1945 r = mailimf_string_write(f, col, "Resent-Cc: ", 11);
1946 if (r != MAILIMF_NO_ERROR)
1947 return r;
1948
1949 r = mailimf_address_list_write(f, col, cc->cc_addr_list);
1950 if (r != MAILIMF_NO_ERROR)
1951 return r;
1952
1953 r = mailimf_string_write(f, col, "\r\n", 2);
1954 if (r != MAILIMF_NO_ERROR)
1955 return r;
1956#if 0
1957 * col = 0;
1958#endif
1959
1960 return MAILIMF_NO_ERROR;
1961}
1962
1963
1964static int mailimf_resent_bcc_write(FILE * f, int * col,
1965 struct mailimf_bcc * bcc)
1966{
1967 int r;
1968
1969 r = mailimf_string_write(f, col, "Resent-Bcc: ", 12);
1970 if (r != MAILIMF_NO_ERROR)
1971 return r;
1972
1973 if (bcc->bcc_addr_list != NULL) {
1974 r = mailimf_address_list_write(f, col, bcc->bcc_addr_list);
1975 if (r != MAILIMF_NO_ERROR)
1976 return r;
1977 }
1978
1979 r = mailimf_string_write(f, col, "\r\n", 2);
1980 if (r != MAILIMF_NO_ERROR)
1981 return r;
1982#if 0
1983 * col = 0;
1984#endif
1985
1986 return MAILIMF_NO_ERROR;
1987}
1988
1989
1990static int
1991mailimf_resent_msg_id_write(FILE * f, int * col,
1992 struct mailimf_message_id * message_id)
1993{
1994 int r;
1995
1996 r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19);
1997 if (r != MAILIMF_NO_ERROR)
1998 return r;
1999
2000 r = mailimf_string_write(f, col, "<", 1);
2001 if (r != MAILIMF_NO_ERROR)
2002 return r;
2003
2004 r = mailimf_string_write(f, col,
2005 message_id->mid_value, strlen(message_id->mid_value));
2006 if (r != MAILIMF_NO_ERROR)
2007 return r;
2008
2009 r = mailimf_string_write(f, col, ">", 1);
2010 if (r != MAILIMF_NO_ERROR)
2011 return r;
2012
2013 r = mailimf_string_write(f, col, "\r\n", 2);
2014 if (r != MAILIMF_NO_ERROR)
2015 return r;
2016#if 0
2017 * col = 0;
2018#endif
2019
2020 return MAILIMF_NO_ERROR;
2021}
diff --git a/libetpan/src/low-level/imf/mailimf_write.h b/libetpan/src/low-level/imf/mailimf_write.h
new file mode 100644
index 0000000..a3441dd
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write.h
@@ -0,0 +1,134 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_H
37
38#define MAILIMF_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47/*
48 mailimf_string_write writes a string to a given stream
49
50 @param f is the stream
51 @param col (* col) is the column number where we will start to
52 write the text, the ending column will be stored in (* col)
53 @param str is the string to write
54*/
55
56int mailimf_string_write(FILE * f, int * col,
57 const char * str, size_t length);
58
59
60/*
61 mailimf_fields_write writes the fields to a given stream
62
63 @param f is the stream
64 @param col (* col) is the column number where we will start to
65 write the text, the ending column will be stored in (* col)
66 @param fields is the fields to write
67*/
68
69int mailimf_fields_write(FILE * f, int * col,
70 struct mailimf_fields * fields);
71
72
73/*
74 mailimf_envelope_fields_write writes only some fields to a given stream
75
76 @param f is the stream
77 @param col (* col) is the column number where we will start to
78 write the text, the ending column will be stored in (* col)
79 @param fields is the fields to write
80*/
81
82int mailimf_envelope_fields_write(FILE * f, int * col,
83 struct mailimf_fields * fields);
84
85
86/*
87 mailimf_field_write writes a field to a given stream
88
89 @param f is the stream
90 @param col (* col) is the column number where we will start to
91 write the text, the ending column will be stored in (* col)
92 @param field is the field to write
93*/
94
95int mailimf_field_write(FILE * f, int * col,
96 struct mailimf_field * field);
97
98/*
99 mailimf_quoted_string_write writes a string that is quoted
100 to a given stream
101
102 @param f is the stream
103 @param col (* col) is the column number where we will start to
104 write the text, the ending column will be stored in (* col)
105 @param string is the string to quote and write
106*/
107
108int mailimf_quoted_string_write(FILE * f, int * col,
109 const char * string, size_t len);
110
111int mailimf_address_list_write(FILE * f, int * col,
112 struct mailimf_address_list * addr_list);
113
114int mailimf_mailbox_list_write(FILE * f, int * col,
115 struct mailimf_mailbox_list * mb_list);
116
117/*
118 mailimf_header_string_write writes a header value and fold the header
119 if needed.
120
121 @param f is the stream
122 @param col (* col) is the column number where we will start to
123 write the text, the ending column will be stored in (* col)
124 @param str is the string to write
125*/
126
127int mailimf_header_string_write(FILE * f, int * col,
128 const char * str, size_t length);
129
130#ifdef __cplusplus
131}
132#endif
133
134#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_file.c b/libetpan/src/low-level/imf/mailimf_write_file.c
new file mode 100644
index 0000000..a1f7187
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_file.c
@@ -0,0 +1,149 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf_write_file.h"
37#include "mailimf_write_generic.h"
38
39static int do_write(void * data, const char * str, size_t length)
40{
41 FILE * f;
42
43 f = data;
44
45 return fwrite(str, 1, length, f);
46}
47
48int mailimf_string_write_file(FILE * f, int * col,
49 const char * str, size_t length)
50{
51 return mailimf_string_write_driver(do_write, f, col, str, length);
52}
53
54int mailimf_fields_write_file(FILE * f, int * col,
55 struct mailimf_fields * fields)
56{
57 return mailimf_fields_write_driver(do_write, f, col, fields);
58}
59
60int mailimf_envelope_fields_write_file(FILE * f, int * col,
61 struct mailimf_fields * fields)
62{
63 return mailimf_envelope_fields_write_driver(do_write, f, col, fields);
64}
65
66int mailimf_field_write_file(FILE * f, int * col,
67 struct mailimf_field * field)
68{
69 return mailimf_field_write_driver(do_write, f, col, field);
70}
71
72int mailimf_quoted_string_write_file(FILE * f, int * col,
73 const char * string, size_t len)
74{
75 return mailimf_quoted_string_write_driver(do_write, f, col, string, len);
76}
77
78int mailimf_address_list_write_file(FILE * f, int * col,
79 struct mailimf_address_list * addr_list)
80{
81 return mailimf_address_list_write_driver(do_write, f, col, addr_list);
82}
83
84int mailimf_mailbox_list_write_file(FILE * f, int * col,
85 struct mailimf_mailbox_list * mb_list)
86{
87 return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list);
88}
89
90int mailimf_header_string_write_file(FILE * f, int * col,
91 const char * str, size_t length)
92{
93 return mailimf_header_string_write_driver(do_write, f, col, str, length);
94}
95
96
97/* binary compatibility with 0.34 - begin */
98
99#ifdef MAILIMF_WRITE_COMPATIBILITY
100int mailimf_string_write(FILE * f, int * col,
101 const char * str, size_t length)
102{
103 return mailimf_string_write_file(f, col, str, length);
104}
105
106int mailimf_fields_write(FILE * f, int * col,
107 struct mailimf_fields * fields)
108{
109 return mailimf_fields_write_file(f, col, fields);
110}
111
112int mailimf_envelope_fields_write(FILE * f, int * col,
113 struct mailimf_fields * fields)
114{
115 return mailimf_envelope_fields_write_file(f, col, fields);
116}
117
118int mailimf_field_write(FILE * f, int * col,
119 struct mailimf_field * field)
120{
121 return mailimf_field_write_file(f, col, field);
122}
123
124int mailimf_quoted_string_write(FILE * f, int * col,
125 const char * string, size_t len)
126{
127 return mailimf_quoted_string_write_file(f, col, string, len);
128}
129
130int mailimf_address_list_write(FILE * f, int * col,
131 struct mailimf_address_list * addr_list)
132{
133 return mailimf_address_list_write_file(f, col, addr_list);
134}
135
136int mailimf_mailbox_list_write(FILE * f, int * col,
137 struct mailimf_mailbox_list * mb_list)
138{
139 return mailimf_mailbox_list_write_file(f, col, mb_list);
140}
141
142int mailimf_header_string_write(FILE * f, int * col,
143 const char * str, size_t length)
144{
145 return mailimf_header_string_write_file(f, col, str, length);
146}
147#endif
148
149/* binary compatibility with 0.34 - end */
diff --git a/libetpan/src/low-level/imf/mailimf_write_file.h b/libetpan/src/low-level/imf/mailimf_write_file.h
new file mode 100644
index 0000000..2b7707f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_file.h
@@ -0,0 +1,169 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_H
37
38#define MAILIMF_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47 //#define MAILIMF_WRITE_COMPATIBILITY
48
49/*
50 mailimf_string_write_file writes a string to a given stream
51
52 @param f is the stream
53 @param col (* col) is the column number where we will start to
54 write the text, the ending column will be stored in (* col)
55 @param str is the string to write
56*/
57
58int mailimf_string_write_file(FILE * f, int * col,
59 const char * str, size_t length);
60
61
62/*
63 mailimf_fields_write_file writes the fields to a given stream
64
65 @param f is the stream
66 @param col (* col) is the column number where we will start to
67 write the text, the ending column will be stored in (* col)
68 @param fields is the fields to write
69*/
70
71int mailimf_fields_write_file(FILE * f, int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write_file writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_file(FILE * f, int * col,
85 struct mailimf_fields * fields);
86
87
88/*
89 mailimf_field_write_file writes a field to a given stream
90
91 @param f is the stream
92 @param col (* col) is the column number where we will start to
93 write the text, the ending column will be stored in (* col)
94 @param field is the field to write
95*/
96
97int mailimf_field_write_file(FILE * f, int * col,
98 struct mailimf_field * field);
99
100/*
101 mailimf_quoted_string_write_file writes a string that is quoted
102 to a given stream
103
104 @param f is the stream
105 @param col (* col) is the column number where we will start to
106 write the text, the ending column will be stored in (* col)
107 @param string is the string to quote and write
108*/
109
110int mailimf_quoted_string_write_file(FILE * f, int * col,
111 const char * string, size_t len);
112
113int mailimf_address_list_write_file(FILE * f, int * col,
114 struct mailimf_address_list * addr_list);
115
116int mailimf_mailbox_list_write_file(FILE * f, int * col,
117 struct mailimf_mailbox_list * mb_list);
118
119/*
120 mailimf_header_string_write_file writes a header value and fold the header
121 if needed.
122
123 @param f is the stream
124 @param col (* col) is the column number where we will start to
125 write the text, the ending column will be stored in (* col)
126 @param str is the string to write
127*/
128
129int mailimf_header_string_write_file(FILE * f, int * col,
130 const char * str, size_t length);
131
132
133
134/* binary compatibility with 0.34 - begin */
135
136#ifdef MAILIMF_WRITE_COMPATIBILITY
137int mailimf_string_write(FILE * f, int * col,
138 const char * str, size_t length);
139
140int mailimf_fields_write(FILE * f, int * col,
141 struct mailimf_fields * fields);
142
143int mailimf_envelope_fields_write(FILE * f, int * col,
144 struct mailimf_fields * fields);
145
146int mailimf_field_write(FILE * f, int * col,
147 struct mailimf_field * field);
148
149int mailimf_quoted_string_write(FILE * f, int * col,
150 const char * string, size_t len);
151
152int mailimf_address_list_write(FILE * f, int * col,
153 struct mailimf_address_list * addr_list);
154
155int mailimf_mailbox_list_write(FILE * f, int * col,
156 struct mailimf_mailbox_list * mb_list);
157
158int mailimf_header_string_write(FILE * f, int * col,
159 const char * str, size_t length);
160#endif
161
162/* binary compatibility with 0.34 - end */
163
164
165#ifdef __cplusplus
166}
167#endif
168
169#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.c b/libetpan/src/low-level/imf/mailimf_write_generic.c
new file mode 100644
index 0000000..74c1d43
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_generic.c
@@ -0,0 +1,2028 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf_write_generic.h"
37
38#include <time.h>
39#include <string.h>
40#include <ctype.h>
41
42#define MAX_MAIL_COL 72
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#define MAX_VALID_IMF_LINE 998
53
54static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
55 int * col,
56 struct mailimf_orig_date * date);
57static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
58 struct mailimf_date_time * date_time);
59static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
60 struct mailimf_from * from);
61static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
62 struct mailimf_sender * sender);
63static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
64 struct mailimf_reply_to * reply_to);
65static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailimf_to * to);
67static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
68 struct mailimf_cc * to);
69static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
70 struct mailimf_bcc * to);
71static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
72 struct mailimf_message_id * message_id);
73static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
74 clist * list);
75static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
76 struct mailimf_in_reply_to *
77 in_reply_to);
78static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
79 struct mailimf_references * references);
80static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
81 struct mailimf_subject * subject);
82
83static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
84 struct mailimf_address * addr);
85static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
86 struct mailimf_group * group);
87
88static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
89 struct mailimf_mailbox * mb);
90
91static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
92 struct mailimf_comments * comments);
93
94static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
95 struct mailimf_optional_field * field);
96
97static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
98 struct mailimf_keywords * keywords);
99
100static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
101 struct mailimf_return * return_path);
102
103static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
104 struct mailimf_path * path);
105
106static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
107 struct mailimf_orig_date * date);
108
109static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
110 struct mailimf_from * from);
111
112static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
113 struct mailimf_sender * sender);
114
115static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
116 struct mailimf_to * to);
117
118static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
119 struct mailimf_cc * cc);
120
121static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
122 struct mailimf_bcc * bcc);
123
124static int
125mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
126 struct mailimf_message_id * message_id);
127
128
129
130/* ************************ */
131
132#if 0
133int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
134 char * str, size_t length)
135{
136 int r;
137
138 if (length != 0) {
139 r = fwrite(str, sizeof(char), length, f);
140 if (r < 0)
141 return MAILIMF_ERROR_FILE;
142 * col += length;
143 }
144
145 return MAILIMF_NO_ERROR;
146}
147#endif
148
149#define CRLF "\r\n"
150#define HEADER_FOLD "\r\n "
151
152static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length)
153{
154 if (length != 0) {
155 int r;
156
157 if (length > 0) {
158 r = do_write(data, str, length);
159 if (r == 0)
160 return MAILIMF_ERROR_FILE;
161 }
162 }
163 return MAILIMF_NO_ERROR;
164}
165
166#define CUT_AT_MAX_VALID_IMF_LINE
167
168int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
169 const char * str, size_t length)
170{
171 int r;
172 size_t count;
173 const char * block_begin;
174 const char * p;
175 int done;
176
177 p = str;
178 block_begin = str;
179 count = 0;
180
181 while (length > 0) {
182#ifdef CUT_AT_MAX_VALID_IMF_LINE
183 if (count >= 998) {
184 /*
185 cut lines at maximum valid length for internet message
186 format standard (currently RFC 2822)
187
188 This should not happen.
189 In case there are some lines larger than 998 in body,
190 the encoding must be changed into base64 or quoted-printable
191 so that wrapping to 72 columns is done.
192 */
193
194 r = flush_buf(do_write, data, block_begin, count);
195 if (r != MAILIMF_NO_ERROR)
196 return r;
197
198 r = do_write(data, CRLF, sizeof(CRLF) - 1);
199 if (r == 0)
200 return MAILIMF_ERROR_FILE;
201
202 count = 0;
203 block_begin = p;
204
205 * col = 0;
206 }
207#endif
208 switch (* p) {
209 case '\n':
210 r = flush_buf(do_write, data, block_begin, count);
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = do_write(data, CRLF, sizeof(CRLF) - 1);
215 if (r == 0)
216 return MAILIMF_ERROR_FILE;
217
218 p ++;
219 length --;
220 count = 0;
221 block_begin = p;
222
223 * col = 0;
224 break;
225
226 case '\r':
227 done = 0;
228 if (length >= 2) {
229 if (* (p + 1) == '\n') {
230 r = flush_buf(do_write, data, block_begin, count);
231 if (r != MAILIMF_NO_ERROR)
232 return r;
233
234 r = do_write(data, CRLF, sizeof(CRLF) - 1);
235 if (r == 0)
236 return MAILIMF_ERROR_FILE;
237
238 p += 2;
239 length -= 2;
240 count = 0;
241 block_begin = p;
242
243 * col = 0;
244
245 done = 1;
246 }
247 }
248 if (!done) {
249 r = flush_buf(do_write, data, block_begin, count);
250 if (r != MAILIMF_NO_ERROR)
251 return r;
252
253 r = do_write(data, CRLF, sizeof(CRLF) - 1);
254 if (r == 0)
255 return MAILIMF_ERROR_FILE;
256
257 p ++;
258 length --;
259 count = 0;
260 block_begin = p;
261
262 * col = 0;
263 }
264 break;
265
266 default:
267 p ++;
268 count ++;
269 length --;
270 break;
271 }
272 }
273
274 r = flush_buf(do_write, data, block_begin, count);
275 if (r != MAILIMF_NO_ERROR)
276 return r;
277 * col += count;
278
279 return MAILIMF_NO_ERROR;
280}
281
282#if 0
283int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
284 char * str, size_t length)
285{
286 char * p;
287 char * block_begin;
288 int current_col;
289 char * last_cut;
290 int r;
291 int first;
292
293 if (* col + length < MAX_MAIL_COL)
294 return mailimf_string_write_driver(do_write, data, col, str, length);
295
296 first = 1;
297 p = str;
298 block_begin = p;
299 last_cut = block_begin;
300 current_col = * col;
301
302 while (1) {
303 if (current_col >= MAX_MAIL_COL) {
304 /* if we reach the maximum recommanded size of line */
305 if (last_cut == block_begin) {
306 /* if we could not find any place to cut */
307 if (first) {
308 /* fold the header */
309 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
310 sizeof(HEADER_FOLD) - 1);
311 if (r != MAILIMF_NO_ERROR)
312 return r;
313 current_col = * col + p - block_begin;
314 first = 0;
315 }
316 else {
317 /* cut the header */
318 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
319 if (r != MAILIMF_NO_ERROR)
320 return r;
321 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
322 sizeof(HEADER_FOLD) - 1);
323 if (r != MAILIMF_NO_ERROR)
324 return r;
325 first = 0;
326 block_begin = p;
327 last_cut = block_begin;
328 current_col = * col + p - block_begin;
329 }
330 }
331 else {
332 /* if we found a place to cut */
333 r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin);
334 if (r != MAILIMF_NO_ERROR)
335 return r;
336 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
337 sizeof(HEADER_FOLD) - 1);
338 if (r != MAILIMF_NO_ERROR)
339 return r;
340 first = 0;
341 block_begin = last_cut;
342 last_cut = block_begin;
343 current_col = * col + p - block_begin;
344 continue;
345 }
346 }
347 else {
348 if (length == 0)
349 break;
350
351 switch (* p) {
352 case ' ':
353 case '\t':
354 last_cut = p;
355 current_col ++;
356 break;
357
358 case '\r':
359 case '\n':
360 current_col = 0;
361 break;
362
363 default:
364 current_col ++;
365 break;
366 }
367
368 p ++;
369 length --;
370 }
371 }
372
373 return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
374}
375#endif
376
377#if 0
378enum {
379 STATE_LOWER_72,
380 STATE_LOWER_72_CUT,
381 STATE_EQUAL_72,
382 STATE_LOWER_998,
383 STATE_EQUAL_998,
384};
385
386int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
387 const char * str, size_t length)
388{
389 int state;
390 const char * p;
391 const char * block_begin;
392 size_t size;
393 const char * cut;
394 int r;
395
396 if (* col < MAX_MAIL_COL)
397 state = STATE_LOWER_72_CUT;
398 else if (* col == MAX_MAIL_COL)
399 state = STATE_EQUAL_72;
400 else if (* col < MAX_VALID_IMF_LINE)
401 state = STATE_LOWER_998;
402 else
403 state = STATE_EQUAL_998;
404
405 p = str;
406 block_begin = p;
407 size = * col;
408 cut = p;
409
410 while (length > 0) {
411 switch (state) {
412 case STATE_LOWER_72:
413 switch (* p) {
414 case '\r':
415 case '\n':
416 p ++;
417 length --;
418 size = 0;
419 break;
420
421 case ' ':
422 case '\t':
423 cut = p;
424 p ++;
425 length --;
426 size ++;
427 state = STATE_LOWER_72_CUT;
428 break;
429
430 default:
431 if (size < MAX_MAIL_COL - 1) {
432 p ++;
433 length --;
434 size ++;
435 }
436 else {
437 state = STATE_EQUAL_72;
438 p ++;
439 length --;
440 size ++;
441 }
442 break;
443 }
444 break; /* end of STATE_LOWER_72 */
445
446 case STATE_LOWER_72_CUT:
447 switch (* p) {
448 case '\r':
449 case '\n':
450 p ++;
451 length --;
452 size = 0;
453 state = STATE_LOWER_72;
454 break;
455
456 case ' ':
457 case '\t':
458 cut = p;
459 p ++;
460 length --;
461 size ++;
462 break;
463
464 default:
465 if (size < MAX_MAIL_COL) {
466 p ++;
467 length --;
468 size ++;
469 }
470 else {
471 r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
475 sizeof(HEADER_FOLD) - 1);
476 if (r != MAILIMF_NO_ERROR)
477 return r;
478 p ++;
479 length --;
480 block_begin = cut;
481 if ((* block_begin == ' ') || (* block_begin == '\t'))
482 block_begin ++;
483 size = p - block_begin + * col;
484 state = STATE_LOWER_72;
485 }
486 break;
487 }
488 break; /* end of STATE_LOWER_72_CUT */
489
490 case STATE_EQUAL_72:
491 switch (* p) {
492 case '\r':
493 case '\n':
494 p ++;
495 length --;
496 size = 0;
497 state = STATE_LOWER_72;
498 break;
499
500 case ' ':
501 case '\t':
502 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
503 if (r != MAILIMF_NO_ERROR)
504 return r;
505 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
506 sizeof(HEADER_FOLD) - 1);
507 if (r != MAILIMF_NO_ERROR)
508 return r;
509 p ++;
510 length --;
511 block_begin = p;
512 size = p - block_begin + * col;
513 state = STATE_LOWER_72;
514 break;
515
516 default:
517 p ++;
518 length --;
519 size ++;
520 state = STATE_LOWER_998;
521 break;
522 }
523 break; /* end of STATE_EQUAL_72 */
524
525 case STATE_LOWER_998:
526 switch (* p) {
527 case '\r':
528 case '\n':
529 p ++;
530 length --;
531 size = 0;
532 state = STATE_LOWER_72;
533 break;
534
535 case ' ':
536 case '\t':
537 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
538 if (r != MAILIMF_NO_ERROR)
539 return r;
540 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
541 sizeof(HEADER_FOLD) - 1);
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544 p ++;
545 length --;
546 block_begin = p;
547 size = p - block_begin + * col;
548 state = STATE_LOWER_72;
549 break;
550
551 default:
552 if (size < MAX_VALID_IMF_LINE - 1) {
553 p ++;
554 length --;
555 size ++;
556 }
557 else {
558 p ++;
559 length --;
560 size = 0;
561 state = STATE_EQUAL_998;
562 }
563 break;
564 }
565 break; /* end of STATE_LOWER_998 */
566
567 case STATE_EQUAL_998:
568 switch (* p) {
569 case '\r':
570 case '\n':
571 p ++;
572 length --;
573 size = 0;
574 state = STATE_LOWER_72;
575 break;
576
577 case ' ':
578 case '\t':
579 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
580 if (r != MAILIMF_NO_ERROR)
581 return r;
582 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
583 sizeof(HEADER_FOLD) - 1);
584 if (r != MAILIMF_NO_ERROR)
585 return r;
586 p ++;
587 length --;
588 block_begin = p;
589 size = p - block_begin + * col;
590 state = STATE_LOWER_72;
591 break;
592
593 default:
594#ifdef CUT_AT_MAX_VALID_IMF_LINE
595 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
596 if (r != MAILIMF_NO_ERROR)
597 return r;
598 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
599 sizeof(HEADER_FOLD) - 1);
600 if (r != MAILIMF_NO_ERROR)
601 return r;
602 p ++;
603 length --;
604 block_begin = p;
605 size = p - block_begin + * col;
606 state = STATE_LOWER_72;
607#else
608 p ++;
609 length --;
610 size ++;
611#endif
612 break;
613 }
614 break; /* end of STATE_EQUAL_998 */
615 }
616 }
617
618 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
619 if (r != MAILIMF_NO_ERROR)
620 return r;
621
622 return MAILIMF_NO_ERROR;
623}
624#endif
625
626enum {
627 STATE_BEGIN,
628 STATE_WORD,
629 STATE_SPACE,
630};
631
632int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
633 const char * str, size_t length)
634{
635 int state;
636 const char * p;
637 const char * word_begin;
638 const char * word_end;
639 const char * next_word;
640 int first;
641
642 state = STATE_BEGIN;
643
644 p = str;
645 word_begin = p;
646 word_end = p;
647 next_word = p;
648 first = 1;
649
650 while (length > 0) {
651 switch (state) {
652 case STATE_BEGIN:
653 switch (* p) {
654 case '\r':
655 case '\n':
656 case ' ':
657 case '\t':
658 p ++;
659 length --;
660 break;
661
662 default:
663 word_begin = p;
664 state = STATE_WORD;
665 break;
666 }
667 break;
668
669 case STATE_SPACE:
670 switch (* p) {
671 case '\r':
672 case '\n':
673 case ' ':
674 case '\t':
675 p ++;
676 length --;
677 break;
678
679 default:
680 word_begin = p;
681 state = STATE_WORD;
682 break;
683 }
684 break;
685
686 case STATE_WORD:
687 switch (* p) {
688 case '\r':
689 case '\n':
690 case ' ':
691 case '\t':
692 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
693 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
694 sizeof(HEADER_FOLD) - 1);
695 else {
696 if (!first)
697 mailimf_string_write_driver(do_write, data, col, " ", 1);
698 }
699 first = 0;
700 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
701 state = STATE_SPACE;
702 break;
703
704 default:
705 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
706 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
707 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
708 sizeof(HEADER_FOLD) - 1);
709 word_begin = p;
710 }
711 p ++;
712 length --;
713 break;
714 }
715 break;
716 }
717 }
718
719 if (state == STATE_WORD) {
720 if (p - word_begin + (* col) >= MAX_MAIL_COL)
721 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
722 sizeof(HEADER_FOLD) - 1);
723 else {
724 if (!first)
725 mailimf_string_write_driver(do_write, data, col, " ", 1);
726 }
727 first = 0;
728 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
729 }
730
731 return MAILIMF_NO_ERROR;
732}
733
734int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
735 struct mailimf_fields * fields)
736{
737 clistiter * cur;
738
739 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
740 cur = clist_next(cur)) {
741 int r;
742 struct mailimf_field * field;
743
744 field = clist_content(cur);
745 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
746 r = mailimf_field_write_driver(do_write, data, col, field);
747 if (r != MAILIMF_NO_ERROR)
748 return r;
749 }
750 }
751
752 return MAILIMF_NO_ERROR;
753}
754
755int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
756 struct mailimf_fields * fields)
757{
758 clistiter * cur;
759
760 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
761 cur = clist_next(cur)) {
762 int r;
763
764 r = mailimf_field_write_driver(do_write, data, col, clist_content(cur));
765 if (r != MAILIMF_NO_ERROR)
766 return r;
767 }
768
769 return MAILIMF_NO_ERROR;
770}
771
772#if 0
773int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
774 struct mailimf_unparsed_fields * fields)
775{
776 clistiter * cur;
777
778 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
779 int r;
780
781 r = mailimf_optional_field_write_driver(do_write, data, col, cur->data);
782 if (r != MAILIMF_NO_ERROR)
783 return r;
784 }
785
786 return MAILIMF_NO_ERROR;
787}
788#endif
789
790int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
791 struct mailimf_field * field)
792{
793 int r;
794
795 switch (field->fld_type) {
796 case MAILIMF_FIELD_RETURN_PATH:
797 r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path);
798 break;
799 case MAILIMF_FIELD_RESENT_DATE:
800 r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date);
801 break;
802 case MAILIMF_FIELD_RESENT_FROM:
803 r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from);
804 break;
805 case MAILIMF_FIELD_RESENT_SENDER:
806 r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender);
807 break;
808 case MAILIMF_FIELD_RESENT_TO:
809 r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to);
810 break;
811 case MAILIMF_FIELD_RESENT_CC:
812 r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc);
813 break;
814 case MAILIMF_FIELD_RESENT_BCC:
815 r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc);
816 break;
817 case MAILIMF_FIELD_RESENT_MSG_ID:
818 r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id);
819 break;
820 case MAILIMF_FIELD_ORIG_DATE:
821 r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date);
822 break;
823 case MAILIMF_FIELD_FROM:
824 r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from);
825 break;
826 case MAILIMF_FIELD_SENDER:
827 r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender);
828 break;
829 case MAILIMF_FIELD_REPLY_TO:
830 r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to);
831 break;
832 case MAILIMF_FIELD_TO:
833 r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to);
834 break;
835 case MAILIMF_FIELD_CC:
836 r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc);
837 break;
838 case MAILIMF_FIELD_BCC:
839 r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc);
840 break;
841 case MAILIMF_FIELD_MESSAGE_ID:
842 r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id);
843 break;
844 case MAILIMF_FIELD_IN_REPLY_TO:
845 r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to);
846 break;
847 case MAILIMF_FIELD_REFERENCES:
848 r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references);
849 break;
850 case MAILIMF_FIELD_SUBJECT:
851 r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject);
852 break;
853 case MAILIMF_FIELD_COMMENTS:
854 r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments);
855 break;
856 case MAILIMF_FIELD_KEYWORDS:
857 r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords);
858 break;
859 case MAILIMF_FIELD_OPTIONAL_FIELD:
860 r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field);
861 break;
862 default:
863 r = MAILIMF_ERROR_INVAL;
864 break;
865 }
866
867 if (r != MAILIMF_NO_ERROR)
868 return r;
869
870 return MAILIMF_NO_ERROR;
871}
872
873
874static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
875 struct mailimf_orig_date * date)
876{
877 int r;
878
879 r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6);
880 if (r != MAILIMF_NO_ERROR)
881 return r;
882
883 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
884 if (r != MAILIMF_NO_ERROR)
885 return r;
886
887 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
888 if (r != MAILIMF_NO_ERROR)
889 return r;
890#if 0
891 * col = 0;
892#endif
893
894 return MAILIMF_NO_ERROR;
895}
896
897#define MAX_DATE_STR 256
898
899/* 0 = Sunday */
900/* y > 1752 */
901
902static int dayofweek(int year, int month, int day)
903{
904 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
905
906 year -= month < 3;
907
908 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
909}
910
911static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
912 "Fri", "Sat"};
913static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
914 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
915
916static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
917 struct mailimf_date_time * date_time)
918{
919 int r;
920 char date_str[MAX_DATE_STR];
921#if 0
922 struct tm tmval;
923 time_t timeval;
924#endif
925 int wday;
926
927#if 0
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_min = date_time->min;
930 tmval.tm_hour = date_time->hour;
931 tmval.tm_sec = date_time->sec;
932 tmval.tm_mday = date_time->day;
933 tmval.tm_mon = date_time->month - 1;
934 tmval.tm_year = date_time->year - 1900;
935 tmval.tm_isdst = 1;
936
937 timeval = mktime(&tmval);
938
939 localtime_r(&timeval, &tmval);
940#endif
941
942 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
943
944 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
945 week_of_day_str[wday], date_time->dt_day,
946 month_str[date_time->dt_month - 1],
947 date_time->dt_year, date_time->dt_hour,
948 date_time->dt_min, date_time->dt_sec,
949 date_time->dt_zone);
950
951 r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str));
952
953 if (r != MAILIMF_NO_ERROR)
954 return r;
955
956 return MAILIMF_NO_ERROR;
957}
958
959static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
960 struct mailimf_from * from)
961{
962 int r;
963
964 r = mailimf_string_write_driver(do_write, data, col, "From: ", 6);
965 if (r != MAILIMF_NO_ERROR)
966 return r;
967
968 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
969 if (r != MAILIMF_NO_ERROR)
970 return r;
971
972 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
973 if (r != MAILIMF_NO_ERROR)
974 return r;
975#if 0
976 * col = 0;
977#endif
978
979 return MAILIMF_NO_ERROR;
980}
981
982static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
983 struct mailimf_sender * sender)
984{
985 int r;
986
987 r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8);
988 if (r != MAILIMF_NO_ERROR)
989 return r;
990
991 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
992 if (r != MAILIMF_NO_ERROR)
993 return r;
994
995 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
996 if (r != MAILIMF_NO_ERROR)
997 return r;
998#if 0
999 * col = 0;
1000#endif
1001
1002 return MAILIMF_NO_ERROR;
1003}
1004
1005static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1006 struct mailimf_reply_to * reply_to)
1007{
1008 int r;
1009
1010 r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10);
1011 if (r != MAILIMF_NO_ERROR)
1012 return r;
1013
1014 r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list);
1015 if (r != MAILIMF_NO_ERROR)
1016 return r;
1017
1018 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1019 if (r != MAILIMF_NO_ERROR)
1020 return r;
1021#if 0
1022 * col = 0;
1023#endif
1024
1025 return MAILIMF_NO_ERROR;
1026}
1027
1028
1029static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1030 struct mailimf_to * to)
1031{
1032 int r;
1033
1034 r = mailimf_string_write_driver(do_write, data, col, "To: ", 4);
1035 if (r != MAILIMF_NO_ERROR)
1036 return r;
1037
1038 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1039 if (r != MAILIMF_NO_ERROR)
1040 return r;
1041
1042 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1043 if (r != MAILIMF_NO_ERROR)
1044 return r;
1045#if 0
1046 * col = 0;
1047#endif
1048
1049 return MAILIMF_NO_ERROR;
1050}
1051
1052
1053static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1054 struct mailimf_cc * cc)
1055{
1056 int r;
1057
1058 r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4);
1059 if (r != MAILIMF_NO_ERROR)
1060 return r;
1061
1062 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1063 if (r != MAILIMF_NO_ERROR)
1064 return r;
1065
1066 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1067 if (r != MAILIMF_NO_ERROR)
1068 return r;
1069#if 0
1070 * col = 0;
1071#endif
1072
1073 return MAILIMF_NO_ERROR;
1074}
1075
1076
1077static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1078 struct mailimf_bcc * bcc)
1079{
1080 int r;
1081
1082 r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5);
1083 if (r != MAILIMF_NO_ERROR)
1084 return r;
1085
1086 if (bcc->bcc_addr_list != NULL) {
1087 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1088 if (r != MAILIMF_NO_ERROR)
1089 return r;
1090 }
1091
1092 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1093 if (r != MAILIMF_NO_ERROR)
1094 return r;
1095#if 0
1096 * col = 0;
1097#endif
1098
1099 return MAILIMF_NO_ERROR;
1100}
1101
1102
1103static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1104 struct mailimf_message_id * message_id)
1105{
1106 int r;
1107
1108 r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12);
1109 if (r != MAILIMF_NO_ERROR)
1110 return r;
1111
1112 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1113 if (r != MAILIMF_NO_ERROR)
1114 return r;
1115
1116 r = mailimf_string_write_driver(do_write, data, col,
1117 message_id->mid_value,
1118 strlen(message_id->mid_value));
1119 if (r != MAILIMF_NO_ERROR)
1120 return r;
1121
1122 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1123 if (r != MAILIMF_NO_ERROR)
1124 return r;
1125
1126 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1127 if (r != MAILIMF_NO_ERROR)
1128 return r;
1129#if 0
1130 * col = 0;
1131#endif
1132
1133 return MAILIMF_NO_ERROR;
1134}
1135
1136
1137static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list)
1138{
1139 clistiter * cur;
1140 int r;
1141 int first;
1142
1143 first = TRUE;
1144
1145 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1146 char * msgid;
1147 size_t len;
1148
1149 msgid = clist_content(cur);
1150 len = strlen(msgid);
1151
1152 /*
1153 XXX - if this is the first message ID, don't fold.
1154 This is a workaround for a bug of old versions of INN.
1155 */
1156 if (!first) {
1157 if (* col > 1) {
1158
1159 if (* col + len >= MAX_MAIL_COL) {
1160 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1161 if (r != MAILIMF_NO_ERROR)
1162 return r;
1163#if 0
1164 * col = 1;
1165#endif
1166 first = TRUE;
1167 }
1168 }
1169 }
1170
1171 if (!first) {
1172 r = mailimf_string_write_driver(do_write, data, col, " ", 1);
1173 if (r != MAILIMF_NO_ERROR)
1174 return r;
1175 }
1176 else {
1177 first = FALSE;
1178 }
1179
1180 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1181 if (r != MAILIMF_NO_ERROR)
1182 return r;
1183
1184 r = mailimf_string_write_driver(do_write, data, col, msgid, len);
1185 if (r != MAILIMF_NO_ERROR)
1186 return r;
1187
1188 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1189 if (r != MAILIMF_NO_ERROR)
1190 return r;
1191 }
1192
1193 return MAILIMF_NO_ERROR;
1194}
1195
1196
1197static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1198 struct mailimf_in_reply_to * in_reply_to)
1199{
1200 int r;
1201
1202 r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13);
1203 if (r != MAILIMF_NO_ERROR)
1204 return r;
1205
1206 r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list);
1207 if (r != MAILIMF_NO_ERROR)
1208 return r;
1209
1210 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1211 if (r != MAILIMF_NO_ERROR)
1212 return r;
1213#if 0
1214 * col = 0;
1215#endif
1216
1217 return MAILIMF_NO_ERROR;
1218}
1219
1220
1221static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1222 struct mailimf_references * references)
1223{
1224 int r;
1225
1226 r = mailimf_string_write_driver(do_write, data, col, "References: ", 12);
1227 if (r != MAILIMF_NO_ERROR)
1228 return r;
1229
1230 r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list);
1231 if (r != MAILIMF_NO_ERROR)
1232 return r;
1233
1234 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1235 if (r != MAILIMF_NO_ERROR)
1236 return r;
1237#if 0
1238 * col = 0;
1239#endif
1240
1241 return MAILIMF_NO_ERROR;
1242}
1243
1244
1245
1246static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1247 struct mailimf_subject * subject)
1248{
1249 int r;
1250
1251 r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9);
1252 if (r != MAILIMF_NO_ERROR)
1253 return r;
1254
1255 r = mailimf_header_string_write_driver(do_write, data, col,
1256 subject->sbj_value, strlen(subject->sbj_value));
1257 if (r != MAILIMF_NO_ERROR)
1258 return r;
1259
1260 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1261 if (r != MAILIMF_NO_ERROR)
1262 return r;
1263#if 0
1264 * col = 0;
1265#endif
1266
1267 return MAILIMF_NO_ERROR;
1268}
1269
1270int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1271 struct mailimf_address_list * addr_list)
1272{
1273 clistiter * cur;
1274 int r;
1275 int first;
1276
1277 first = TRUE;
1278
1279 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1280 cur = clist_next(cur)) {
1281 struct mailimf_address * addr;
1282
1283 addr = clist_content(cur);
1284
1285 if (!first) {
1286 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1287 if (r != MAILIMF_NO_ERROR)
1288 return r;
1289 }
1290 else {
1291 first = FALSE;
1292 }
1293
1294 r = mailimf_address_write_driver(do_write, data, col, addr);
1295 if (r != MAILIMF_NO_ERROR)
1296 return r;
1297 }
1298
1299 return MAILIMF_NO_ERROR;
1300}
1301
1302
1303static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1304 struct mailimf_address * addr)
1305{
1306 int r;
1307
1308 switch(addr->ad_type) {
1309 case MAILIMF_ADDRESS_MAILBOX:
1310 r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox);
1311 if (r != MAILIMF_NO_ERROR)
1312 return r;
1313
1314 break;
1315
1316 case MAILIMF_ADDRESS_GROUP:
1317 r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group);
1318 if (r != MAILIMF_NO_ERROR)
1319 return r;
1320
1321 break;
1322 }
1323
1324 return MAILIMF_NO_ERROR;
1325}
1326
1327
1328static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1329 struct mailimf_group * group)
1330{
1331 int r;
1332
1333 r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name,
1334 strlen(group->grp_display_name));
1335 if (r != MAILIMF_NO_ERROR)
1336 return r;
1337
1338 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1339 if (r != MAILIMF_NO_ERROR)
1340 return r;
1341
1342 if (group->grp_mb_list != NULL) {
1343 r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list);
1344 if (r != MAILIMF_NO_ERROR)
1345 return r;
1346 }
1347
1348 r = mailimf_string_write_driver(do_write, data, col, ";", 1);
1349 if (r != MAILIMF_NO_ERROR)
1350 return r;
1351
1352 return MAILIMF_NO_ERROR;
1353}
1354
1355
1356int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1357 struct mailimf_mailbox_list * mb_list)
1358{
1359 clistiter * cur;
1360 int r;
1361 int first;
1362
1363 first = TRUE;
1364
1365 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1366 cur = clist_next(cur)) {
1367 struct mailimf_mailbox * mb;
1368
1369 mb = clist_content(cur);
1370
1371 if (!first) {
1372 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1373 if (r != MAILIMF_NO_ERROR)
1374 return r;
1375 }
1376 else {
1377 first = FALSE;
1378 }
1379
1380 r = mailimf_mailbox_write_driver(do_write, data, col, mb);
1381 if (r != MAILIMF_NO_ERROR)
1382 return r;
1383 }
1384
1385 return MAILIMF_NO_ERROR;
1386}
1387
1388
1389int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1390 const char * string, size_t len)
1391{
1392 int r;
1393 size_t i;
1394
1395 r = do_write(data, "\"", 1);
1396 if (r == 0)
1397 return MAILIMF_ERROR_FILE;
1398 for(i = 0 ; i < len ; i ++) {
1399 switch (string[i]) {
1400 case '\\':
1401 case '\"':
1402 r = do_write(data, "\\", 1);
1403 if (r == 0)
1404 return MAILIMF_ERROR_FILE;
1405 r = do_write(data, &string[i], 1);
1406 if (r == 0)
1407 return MAILIMF_ERROR_FILE;
1408 (* col) += 2;
1409 break;
1410
1411 default:
1412 r = do_write(data, &string[i], 1);
1413 if (r == 0)
1414 return MAILIMF_ERROR_FILE;
1415 (* col) ++;
1416 break;
1417 }
1418 }
1419 r = do_write(data, "\"", 1);
1420 if (r == 0)
1421 return MAILIMF_ERROR_FILE;
1422
1423 return MAILIMF_NO_ERROR;
1424}
1425
1426
1427/*
1428static int
1429atext = ALPHA / DIGIT / ; Any character except controls,
1430 "!" / "#" / ; SP, and specials.
1431 "$" / "%" / ; Used for atoms
1432 "&" / "'" /
1433 "*" / "+" /
1434 "-" / "/" /
1435 "=" / "?" /
1436 "^" / "_" /
1437 "`" / "{" /
1438 "|" / "}" /
1439 "~"
1440*/
1441
1442static int is_atext(const char * s)
1443{
1444 const char * p;
1445
1446 for(p = s ; * p != 0 ; p ++) {
1447 if (isalpha((unsigned char) * p))
1448 continue;
1449 if (isdigit((unsigned char) * p))
1450 continue;
1451 switch (*p) {
1452 case ' ':
1453 case '\t':
1454 case '!':
1455 case '#':
1456 case '$':
1457 case '%':
1458 case '&':
1459 case '\'':
1460 case '*':
1461 case '+':
1462 case '-':
1463 case '/':
1464 case '=':
1465 case '?':
1466 case '^':
1467 case '_':
1468 case '`':
1469 case '{':
1470 case '|':
1471 case '}':
1472 case '~':
1473 break;
1474 default:
1475 return 0;
1476 }
1477 }
1478
1479 return 1;
1480}
1481
1482static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1483 struct mailimf_mailbox * mb)
1484{
1485 int r;
1486 int do_fold;
1487
1488#if 0
1489 if (* col > 1) {
1490
1491 if (mb->mb_display_name != NULL) {
1492 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1493 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1494 if (r != MAILIMF_NO_ERROR)
1495 return r;
1496#if 0
1497 * col = 1;
1498#endif
1499 }
1500 }
1501 }
1502#endif
1503
1504 if (mb->mb_display_name) {
1505
1506 if (is_atext(mb->mb_display_name)) {
1507 r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name,
1508 strlen(mb->mb_display_name));
1509 if (r != MAILIMF_NO_ERROR)
1510 return r;
1511 }
1512 else {
1513 if (mb->mb_display_name != NULL) {
1514 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1515 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1516 if (r != MAILIMF_NO_ERROR)
1517 return r;
1518 }
1519 }
1520
1521 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1522 return MAILIMF_ERROR_INVAL;
1523
1524 r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name,
1525 strlen(mb->mb_display_name));
1526 if (r != MAILIMF_NO_ERROR)
1527 return r;
1528 }
1529
1530 do_fold = 0;
1531 if (* col > 1) {
1532
1533 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1534 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1535 if (r != MAILIMF_NO_ERROR)
1536 return r;
1537#if 0
1538 * col = 1;
1539#endif
1540 do_fold = 1;
1541 }
1542 }
1543
1544 if (do_fold)
1545 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1546 else
1547 r = mailimf_string_write_driver(do_write, data, col, " <", 2);
1548 if (r != MAILIMF_NO_ERROR)
1549 return r;
1550
1551 r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec,
1552 strlen(mb->mb_addr_spec));
1553 if (r != MAILIMF_NO_ERROR)
1554 return r;
1555
1556 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1557 if (r != MAILIMF_NO_ERROR)
1558 return r;
1559 }
1560 else {
1561 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1562 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1563 if (r != MAILIMF_NO_ERROR)
1564 return r;
1565 }
1566
1567 r = mailimf_string_write_driver(do_write, data, col,
1568 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1569 if (r != MAILIMF_NO_ERROR)
1570 return r;
1571 }
1572
1573
1574 return MAILIMF_NO_ERROR;
1575}
1576
1577static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1578 struct mailimf_comments * comments)
1579{
1580 int r;
1581
1582 r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10);
1583 if (r != MAILIMF_NO_ERROR)
1584 return r;
1585
1586 r = mailimf_header_string_write_driver(do_write, data, col,
1587 comments->cm_value, strlen(comments->cm_value));
1588 if (r != MAILIMF_NO_ERROR)
1589 return r;
1590
1591 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1592 if (r != MAILIMF_NO_ERROR)
1593 return r;
1594#if 0
1595 * col = 0;
1596#endif
1597
1598 return MAILIMF_NO_ERROR;
1599}
1600
1601static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1602 struct mailimf_optional_field * field)
1603{
1604 int r;
1605
1606 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1607 return MAILIMF_ERROR_INVAL;
1608
1609 r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name));
1610 if (r != MAILIMF_NO_ERROR)
1611 return r;
1612
1613 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1614 if (r != MAILIMF_NO_ERROR)
1615 return r;
1616
1617 r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value,
1618 strlen(field->fld_value));
1619 if (r != MAILIMF_NO_ERROR)
1620 return r;
1621
1622#if 0
1623 /* XXX parsing debug */
1624 mailimf_string_write_driver(do_write, data, col, " (X)", 4);
1625#endif
1626
1627 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1628 if (r != MAILIMF_NO_ERROR)
1629 return r;
1630#if 0
1631 * col = 0;
1632#endif
1633
1634 return MAILIMF_NO_ERROR;
1635}
1636
1637static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1638 struct mailimf_keywords * keywords)
1639{
1640 int r;
1641 clistiter * cur;
1642 int first;
1643
1644 r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10);
1645 if (r != MAILIMF_NO_ERROR)
1646 return r;
1647
1648 first = TRUE;
1649
1650 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1651 cur = clist_next(cur)) {
1652 char * keyword;
1653 size_t len;
1654
1655 keyword = clist_content(cur);
1656 len = strlen(keyword);
1657
1658 if (!first) {
1659 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1660 if (r != MAILIMF_NO_ERROR)
1661 return r;
1662 }
1663 else {
1664 first = FALSE;
1665 }
1666
1667#if 0
1668 if (* col > 1) {
1669
1670 if (* col + len >= MAX_MAIL_COL) {
1671 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1672 if (r != MAILIMF_NO_ERROR)
1673 return r;
1674#if 0
1675 * col = 1;
1676#endif
1677 }
1678 }
1679#endif
1680
1681 r = mailimf_header_string_write_driver(do_write, data, col, keyword, len);
1682 if (r != MAILIMF_NO_ERROR)
1683 return r;
1684 }
1685
1686 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1687 if (r != MAILIMF_NO_ERROR)
1688 return r;
1689#if 0
1690 * col = 0;
1691#endif
1692
1693 return MAILIMF_NO_ERROR;
1694}
1695
1696#if 0
1697static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1698 struct mailimf_delivering_info * info)
1699{
1700 clistiter * cur;
1701 int r;
1702
1703 for(cur = clist_begin(info->received_fields) ;
1704 cur != NULL ; cur = cur->next) {
1705 struct mailimf_trace_resent_fields * field;
1706
1707 field = cur->data;
1708
1709 r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field);
1710 if (r != MAILIMF_NO_ERROR)
1711 return r;
1712 }
1713
1714 return MAILIMF_NO_ERROR;
1715}
1716
1717
1718static int
1719mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1720 struct mailimf_trace_resent_fields * field)
1721{
1722 int r;
1723
1724 if (field->return_path != NULL) {
1725 r = mailimf_return_write_driver(do_write, data, col, field->return_path);
1726 if (r != MAILIMF_NO_ERROR)
1727 return r;
1728 }
1729
1730 if (field->resent_fields != NULL) {
1731 r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields);
1732 if (r != MAILIMF_NO_ERROR)
1733 return r;
1734 }
1735
1736 return MAILIMF_NO_ERROR;
1737}
1738#endif
1739
1740static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1741 struct mailimf_return * return_path)
1742{
1743 int r;
1744
1745 r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13);
1746 if (r != MAILIMF_NO_ERROR)
1747 return r;
1748
1749 r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path);
1750 if (r != MAILIMF_NO_ERROR)
1751 return r;
1752
1753 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1754 if (r != MAILIMF_NO_ERROR)
1755 return r;
1756#if 0
1757 * col = 0;
1758#endif
1759
1760 return MAILIMF_NO_ERROR;
1761}
1762
1763static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1764 struct mailimf_path * path)
1765{
1766 int r;
1767
1768 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1769 if (r != MAILIMF_NO_ERROR)
1770 return r;
1771
1772 r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec,
1773 strlen(path->pt_addr_spec));
1774 if (r != MAILIMF_NO_ERROR)
1775 return r;
1776
1777 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1778 if (r != MAILIMF_NO_ERROR)
1779 return r;
1780
1781 return MAILIMF_NO_ERROR;
1782}
1783
1784#if 0
1785static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1786 struct mailimf_resent_fields_list *
1787 resent_fields)
1788{
1789 clistiter * cur;
1790 int r;
1791
1792 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1793 struct mailimf_resent_field * field;
1794
1795 field = cur->data;
1796
1797 r = mailimf_resent_field_write_driver(do_write, data, col, field);
1798 if (r != MAILIMF_NO_ERROR)
1799 return r;
1800 }
1801
1802 return MAILIMF_NO_ERROR;
1803}
1804
1805
1806
1807static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1808 struct mailimf_resent_field *
1809 resent_field)
1810{
1811 int r;
1812
1813 switch (resent_field->type) {
1814 case MAILIMF_RESENT_FIELD_DATE:
1815 r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date);
1816 break;
1817
1818 case MAILIMF_RESENT_FIELD_FROM:
1819 r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from);
1820 break;
1821
1822 case MAILIMF_RESENT_FIELD_SENDER:
1823 r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender);
1824 break;
1825
1826 case MAILIMF_RESENT_FIELD_TO:
1827 r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to);
1828 break;
1829
1830 case MAILIMF_RESENT_FIELD_CC:
1831 r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc);
1832 break;
1833
1834 case MAILIMF_RESENT_FIELD_BCC:
1835 r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc);
1836 break;
1837
1838 case MAILIMF_RESENT_FIELD_MSG_ID:
1839 r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id);
1840 break;
1841 default:
1842 r = MAILIMF_ERROR_INVAL;
1843 break;
1844 }
1845
1846
1847 if (r != MAILIMF_NO_ERROR)
1848 return r;
1849
1850 return MAILIMF_NO_ERROR;
1851}
1852#endif
1853
1854static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1855 struct mailimf_orig_date * date)
1856{
1857 int r;
1858
1859 r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13);
1860 if (r != MAILIMF_NO_ERROR)
1861 return r;
1862
1863 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
1864 if (r != MAILIMF_NO_ERROR)
1865 return r;
1866
1867 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1868 if (r != MAILIMF_NO_ERROR)
1869 return r;
1870#if 0
1871 * col = 0;
1872#endif
1873
1874 return MAILIMF_NO_ERROR;
1875}
1876
1877static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1878 struct mailimf_from * from)
1879{
1880 int r;
1881
1882 r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13);
1883 if (r != MAILIMF_NO_ERROR)
1884 return r;
1885
1886 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
1887 if (r != MAILIMF_NO_ERROR)
1888 return r;
1889
1890 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1891 if (r != MAILIMF_NO_ERROR)
1892 return r;
1893#if 0
1894 * col = 0;
1895#endif
1896
1897 return MAILIMF_NO_ERROR;
1898}
1899
1900static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1901 struct mailimf_sender * sender)
1902{
1903 int r;
1904
1905 r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15);
1906 if (r != MAILIMF_NO_ERROR)
1907 return r;
1908
1909 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
1910 if (r != MAILIMF_NO_ERROR)
1911 return r;
1912
1913 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1914 if (r != MAILIMF_NO_ERROR)
1915 return r;
1916#if 0
1917 * col = 0;
1918#endif
1919
1920 return MAILIMF_NO_ERROR;
1921}
1922
1923static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1924 struct mailimf_to * to)
1925{
1926 int r;
1927
1928 r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11);
1929 if (r != MAILIMF_NO_ERROR)
1930 return r;
1931
1932 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1933 if (r != MAILIMF_NO_ERROR)
1934 return r;
1935
1936 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1937 if (r != MAILIMF_NO_ERROR)
1938 return r;
1939#if 0
1940 * col = 0;
1941#endif
1942
1943 return MAILIMF_NO_ERROR;
1944}
1945
1946
1947static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1948 struct mailimf_cc * cc)
1949{
1950 int r;
1951
1952 r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11);
1953 if (r != MAILIMF_NO_ERROR)
1954 return r;
1955
1956 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1957 if (r != MAILIMF_NO_ERROR)
1958 return r;
1959
1960 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1961 if (r != MAILIMF_NO_ERROR)
1962 return r;
1963#if 0
1964 * col = 0;
1965#endif
1966
1967 return MAILIMF_NO_ERROR;
1968}
1969
1970
1971static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1972 struct mailimf_bcc * bcc)
1973{
1974 int r;
1975
1976 r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12);
1977 if (r != MAILIMF_NO_ERROR)
1978 return r;
1979
1980 if (bcc->bcc_addr_list != NULL) {
1981 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1982 if (r != MAILIMF_NO_ERROR)
1983 return r;
1984 }
1985
1986 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1987 if (r != MAILIMF_NO_ERROR)
1988 return r;
1989#if 0
1990 * col = 0;
1991#endif
1992
1993 return MAILIMF_NO_ERROR;
1994}
1995
1996
1997static int
1998mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1999 struct mailimf_message_id * message_id)
2000{
2001 int r;
2002
2003 r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19);
2004 if (r != MAILIMF_NO_ERROR)
2005 return r;
2006
2007 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
2008 if (r != MAILIMF_NO_ERROR)
2009 return r;
2010
2011 r = mailimf_string_write_driver(do_write, data, col,
2012 message_id->mid_value, strlen(message_id->mid_value));
2013 if (r != MAILIMF_NO_ERROR)
2014 return r;
2015
2016 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
2017 if (r != MAILIMF_NO_ERROR)
2018 return r;
2019
2020 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
2021 if (r != MAILIMF_NO_ERROR)
2022 return r;
2023#if 0
2024 * col = 0;
2025#endif
2026
2027 return MAILIMF_NO_ERROR;
2028}
diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.h b/libetpan/src/low-level/imf/mailimf_write_generic.h
new file mode 100644
index 0000000..c207d7e
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_generic.h
@@ -0,0 +1,142 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_GENERIC_H
37
38#define MAILIMF_WRITE_GENERIC_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46
47/*
48 mailimf_string_write writes a string to a given stream
49
50 @param f is the stream
51 @param col (* col) is the column number where we will start to
52 write the text, the ending column will be stored in (* col)
53 @param str is the string to write
54*/
55
56int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
57 int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write writes the fields to a given stream
63
64 @param f is the stream
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
71 int * col,
72 struct mailimf_fields * fields);
73
74
75/*
76 mailimf_envelope_fields_write writes only some fields to a given stream
77
78 @param f is the stream
79 @param col (* col) is the column number where we will start to
80 write the text, the ending column will be stored in (* col)
81 @param fields is the fields to write
82*/
83
84int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
85 int * col,
86 struct mailimf_fields * fields);
87
88
89/*
90 mailimf_field_write writes a field to a given stream
91
92 @param f is the stream
93 @param col (* col) is the column number where we will start to
94 write the text, the ending column will be stored in (* col)
95 @param field is the field to write
96*/
97
98int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
99 int * col,
100 struct mailimf_field * field);
101
102/*
103 mailimf_quoted_string_write writes a string that is quoted
104 to a given stream
105
106 @param f is the stream
107 @param col (* col) is the column number where we will start to
108 write the text, the ending column will be stored in (* col)
109 @param string is the string to quote and write
110*/
111
112int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
113 int * col,
114 const char * string, size_t len);
115
116int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
117 int * col,
118 struct mailimf_address_list * addr_list);
119
120int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
121 int * col,
122 struct mailimf_mailbox_list * mb_list);
123
124/*
125 mailimf_header_string_write writes a header value and fold the header
126 if needed.
127
128 @param f is the stream
129 @param col (* col) is the column number where we will start to
130 write the text, the ending column will be stored in (* col)
131 @param str is the string to write
132*/
133
134int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
135 int * col,
136 const char * str, size_t length);
137
138#ifdef __cplusplus
139}
140#endif
141
142#endif
diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.c b/libetpan/src/low-level/imf/mailimf_write_mem.c
new file mode 100644
index 0000000..00c043f
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_mem.c
@@ -0,0 +1,98 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf_write_mem.h"
37#include "mailimf_write_generic.h"
38
39static int do_write(void * data, const char * str, size_t length)
40{
41 MMAPString * f;
42
43 f = data;
44
45 if (mmap_string_append_len(f, str, length) == NULL)
46 return 0;
47 else
48 return length;
49}
50
51int mailimf_string_write_mem(MMAPString * f, int * col,
52 const char * str, size_t length)
53{
54 return mailimf_string_write_driver(do_write, f, col, str, length);
55}
56
57int mailimf_fields_write_mem(MMAPString * f, int * col,
58 struct mailimf_fields * fields)
59{
60 return mailimf_fields_write_driver(do_write, f, col, fields);
61}
62
63int mailimf_envelope_fields_write_mem(MMAPString * f, int * col,
64 struct mailimf_fields * fields)
65{
66 return mailimf_envelope_fields_write_driver(do_write, f, col, fields);
67}
68
69int mailimf_field_write_mem(MMAPString * f, int * col,
70 struct mailimf_field * field)
71{
72 return mailimf_field_write_driver(do_write, f, col, field);
73}
74
75int mailimf_quoted_string_write_mem(MMAPString * f, int * col,
76 const char * string, size_t len)
77{
78 return mailimf_quoted_string_write_driver(do_write, f, col, string, len);
79}
80
81int mailimf_address_list_write_mem(MMAPString * f, int * col,
82 struct mailimf_address_list * addr_list)
83{
84 return mailimf_address_list_write_driver(do_write, f, col, addr_list);
85}
86
87int mailimf_mailbox_list_write_mem(MMAPString * f, int * col,
88 struct mailimf_mailbox_list * mb_list)
89{
90 return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list);
91}
92
93int mailimf_header_string_write_mem(MMAPString * f, int * col,
94 const char * str, size_t length)
95{
96 return mailimf_header_string_write_driver(do_write, f, col, str, length);
97}
98
diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.h b/libetpan/src/low-level/imf/mailimf_write_mem.h
new file mode 100644
index 0000000..796f178
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_mem.h
@@ -0,0 +1,135 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILIMF_WRITE_MEM_H
37
38#define MAILIMF_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <stdio.h>
45#include <libetpan/mailimf_types.h>
46#include <libetpan/mmapstring.h>
47
48/*
49 mailimf_string_write_mem appends a string to a given string
50
51 @param f is the string
52 @param col (* col) is the column number where we will start to
53 write the text, the ending column will be stored in (* col)
54 @param str is the string to write
55*/
56
57int mailimf_string_write_mem(MMAPString * f, int * col,
58 const char * str, size_t length);
59
60
61/*
62 mailimf_fields_write_mem appends the fields to a given string
63
64 @param f is the string
65 @param col (* col) is the column number where we will start to
66 write the text, the ending column will be stored in (* col)
67 @param fields is the fields to write
68*/
69
70int mailimf_fields_write_mem(MMAPString * f, int * col,
71 struct mailimf_fields * fields);
72
73
74/*
75 mailimf_envelope_fields_write_mem appends some fields to a given string
76
77 @param f is the string
78 @param col (* col) is the column number where we will start to
79 write the text, the ending column will be stored in (* col)
80 @param fields is the fields to write
81*/
82
83int mailimf_envelope_fields_write_mem(MMAPString * f, int * col,
84 struct mailimf_fields * fields);
85
86
87/*
88 mailimf_field_write_mem appends a field to a given string
89
90 @param f is the string
91 @param col (* col) is the column number where we will start to
92 write the text, the ending column will be stored in (* col)
93 @param field is the field to write
94*/
95
96int mailimf_field_write_mem(MMAPString * f, int * col,
97 struct mailimf_field * field);
98
99/*
100 mailimf_quoted_string_write_mem appends a string that is quoted
101 to a given string
102
103 @param f is the string
104 @param col (* col) is the column number where we will start to
105 write the text, the ending column will be stored in (* col)
106 @param string is the string to quote and write
107*/
108
109int mailimf_quoted_string_write_mem(MMAPString * f, int * col,
110 const char * string, size_t len);
111
112int mailimf_address_list_write_mem(MMAPString * f, int * col,
113 struct mailimf_address_list * addr_list);
114
115int mailimf_mailbox_list_write_mem(MMAPString * f, int * col,
116 struct mailimf_mailbox_list * mb_list);
117
118/*
119 mailimf_header_string_write_mem appends a header value and fold the header
120 if needed.
121
122 @param f is the string
123 @param col (* col) is the column number where we will start to
124 write the text, the ending column will be stored in (* col)
125 @param str is the string to write
126*/
127
128int mailimf_header_string_write_mem(MMAPString * f, int * col,
129 const char * str, size_t length);
130
131#ifdef __cplusplus
132}
133#endif
134
135#endif
diff --git a/libetpan/src/low-level/maildir/maildir.c b/libetpan/src/low-level/maildir/maildir.c
new file mode 100644
index 0000000..98b9f87
--- a/dev/null
+++ b/libetpan/src/low-level/maildir/maildir.c
@@ -0,0 +1,798 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildir.h"
37
38#include <string.h>
39#include <stdlib.h>
40#include <stdio.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <dirent.h>
44#include <time.h>
45#include <sys/stat.h>
46#include <sys/mman.h>
47#include <errno.h>
48#include <fcntl.h>
49
50#ifdef LIBETPAN_SYSTEM_BASENAME
51#include <libgen.h>
52#endif
53
54/*
55 We suppose the maildir mailbox remains on one unique filesystem.
56*/
57
58struct maildir * maildir_new(const char * path)
59{
60 struct maildir * md;
61
62 md = malloc(sizeof(* md));
63 if (md == NULL)
64 goto err;
65
66 md->mdir_counter = 0;
67 md->mdir_mtime_new = (time_t) -1;
68 md->mdir_mtime_cur = (time_t) -1;
69
70 md->mdir_pid = getpid();
71 gethostname(md->mdir_hostname, sizeof(md->mdir_hostname));
72 strncpy(md->mdir_path, path, sizeof(md->mdir_path));
73 md->mdir_path[PATH_MAX - 1] = '\0';
74
75 md->mdir_msg_list = carray_new(128);
76 if (md->mdir_msg_list == NULL)
77 goto free;
78
79 md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE);
80 if (md->mdir_msg_hash == NULL)
81 goto free_msg_list;
82
83 return md;
84
85 free_msg_list:
86 carray_free(md->mdir_msg_list);
87 free:
88 free(md);
89 err:
90 return NULL;
91}
92
93static void maildir_flush(struct maildir * md, int msg_new);
94
95void maildir_free(struct maildir * md)
96{
97 maildir_flush(md, 0);
98 maildir_flush(md, 1);
99 chash_free(md->mdir_msg_hash);
100 carray_free(md->mdir_msg_list);
101 free(md);
102}
103
104#define MAX_TRY_ALLOC 32
105
106static char * maildir_get_new_message_filename(struct maildir * md,
107 char * tmpfile)
108{
109 char filename[PATH_MAX];
110 char basename[PATH_MAX];
111 int k;
112 time_t now;
113 int got_file;
114 int r;
115
116 got_file = 0;
117 now = time(NULL);
118 k = 0;
119 while (k < MAX_TRY_ALLOC) {
120 snprintf(basename, sizeof(basename), "%lu.%u_%u.%s",
121 (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname);
122 snprintf(filename, sizeof(filename), "%s/tmp/%s",
123 md->mdir_path, basename);
124
125 if (link(tmpfile, filename) == 0) {
126 got_file = 1;
127 unlink(tmpfile);
128 }
129 else if (errno == EXDEV) {
130 unlink(tmpfile);
131 return NULL;
132 }
133 else if (errno == EPERM) {
134 r = rename(tmpfile, filename);
135 if (r < 0) {
136 unlink(tmpfile);
137 return NULL;
138 }
139 got_file = 1;
140 }
141
142 if (got_file) {
143 char * dup_filename;
144
145 dup_filename = strdup(filename);
146 if (dup_filename == NULL) {
147 unlink(filename);
148 return NULL;
149 }
150
151 md->mdir_counter ++;
152
153 return dup_filename;
154 }
155
156 md->mdir_counter ++;
157 k ++;
158 }
159
160 return NULL;
161}
162
163
164static void msg_free(struct maildir_msg * msg)
165{
166 free(msg->msg_uid);
167 free(msg->msg_filename);
168 free(msg);
169}
170
171/*
172 msg_new()
173
174 filename is given without path
175*/
176
177static struct maildir_msg * msg_new(char * filename, int new_msg)
178{
179 struct maildir_msg * msg;
180 char * p;
181 int flags;
182 size_t uid_len;
183 char * begin_uid;
184
185 /* name of file : xxx-xxx_xxx-xxx:2,SRFT */
186
187 msg = malloc(sizeof(* msg));
188 if (msg == NULL)
189 goto err;
190
191 msg->msg_filename = strdup(filename);
192 if (msg->msg_filename == NULL)
193 goto free;
194
195 begin_uid = filename;
196
197 uid_len = strlen(begin_uid);
198
199 flags = 0;
200 p = strstr(filename, ":2,");
201 if (p != NULL) {
202 uid_len = p - begin_uid;
203
204 p += 3;
205
206 /* parse flags */
207 while (* p != '\0') {
208 switch (* p) {
209 case 'S':
210 flags |= MAILDIR_FLAG_SEEN;
211 break;
212 case 'R':
213 flags |= MAILDIR_FLAG_REPLIED;
214 break;
215 case 'F':
216 flags |= MAILDIR_FLAG_FLAGGED;
217 break;
218 case 'T':
219 flags |= MAILDIR_FLAG_TRASHED;
220 break;
221 }
222 p ++;
223 }
224 }
225
226 if (new_msg)
227 flags |= MAILDIR_FLAG_NEW;
228
229 msg->msg_flags = flags;
230
231 msg->msg_uid = malloc(uid_len + 1);
232 if (msg->msg_uid == NULL)
233 goto free_filename;
234
235 strncpy(msg->msg_uid, begin_uid, uid_len);
236 msg->msg_uid[uid_len] = '\0';
237
238 return msg;
239
240 free_filename:
241 free(msg->msg_filename);
242 free:
243 free(msg);
244 err:
245 return NULL;
246}
247
248static void maildir_flush(struct maildir * md, int msg_new)
249{
250 unsigned int i;
251
252 i = 0;
253 while (i < carray_count(md->mdir_msg_list)) {
254 struct maildir_msg * msg;
255 int delete;
256
257 msg = carray_get(md->mdir_msg_list, i);
258
259 if (msg_new) {
260 delete = 0;
261 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
262 delete = 1;
263 }
264 else {
265 delete = 1;
266 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
267 delete = 0;
268 }
269
270 if (delete) {
271 chashdatum key;
272
273 key.data = msg->msg_uid;
274 key.len = strlen(msg->msg_uid);
275 chash_delete(md->mdir_msg_hash, &key, NULL);
276
277 carray_delete(md->mdir_msg_list, i);
278 msg_free(msg);
279 }
280 else {
281 i ++;
282 }
283 }
284}
285
286static int add_message(struct maildir * md,
287 char * filename, int is_new)
288{
289 struct maildir_msg * msg;
290 chashdatum key;
291 chashdatum value;
292 unsigned int i;
293 int res;
294 int r;
295
296 msg = msg_new(filename, is_new);
297 if (msg == NULL) {
298 res = MAILDIR_ERROR_MEMORY;
299 goto err;
300 }
301
302 r = carray_add(md->mdir_msg_list, msg, &i);
303 if (r < 0) {
304 res = MAILDIR_ERROR_MEMORY;
305 goto free_msg;
306 }
307
308 key.data = msg->msg_uid;
309 key.len = strlen(msg->msg_uid);
310 value.data = msg;
311 value.len = 0;
312
313 r = chash_set(md->mdir_msg_hash, &key, &value, NULL);
314 if (r < 0) {
315 res = MAILDIR_ERROR_MEMORY;
316 goto delete;
317 }
318
319 return MAILDIR_NO_ERROR;
320
321 delete:
322 carray_delete(md->mdir_msg_list, i);
323 free_msg:
324 msg_free(msg);
325 err:
326 return res;
327}
328
329static int add_directory(struct maildir * md, char * path, int is_new)
330{
331 DIR * d;
332 struct dirent * entry;
333 int res;
334 int r;
335#if 0
336 char filename[PATH_MAX];
337#endif
338
339 d = opendir(path);
340 if (d == NULL) {
341 res = MAILDIR_ERROR_DIRECTORY;
342 goto err;
343 }
344
345 while ((entry = readdir(d)) != NULL) {
346#if 0
347 struct stat stat_info;
348
349 snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
350
351 r = stat(filename, &stat_info);
352 if (r < 0)
353 continue;
354
355 if (S_ISDIR(stat_info.st_mode))
356 continue;
357#endif
358
359 if (entry->d_name[0] == '.')
360 continue;
361
362 r = add_message(md, entry->d_name, is_new);
363 if (r != MAILDIR_NO_ERROR) {
364 /* ignore errors */
365 }
366 }
367
368 closedir(d);
369
370 return MAILDIR_NO_ERROR;
371
372 err:
373 return res;
374}
375
376int maildir_update(struct maildir * md)
377{
378 struct stat stat_info;
379 char path_new[PATH_MAX];
380 char path_cur[PATH_MAX];
381 char path_maildirfolder[PATH_MAX];
382 int r;
383 int res;
384 int changed;
385
386 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
387 snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path);
388
389 changed = 0;
390
391 /* did new/ changed ? */
392
393 r = stat(path_new, &stat_info);
394 if (r < 0) {
395 res = MAILDIR_ERROR_DIRECTORY;
396 goto free;
397 }
398
399 if (md->mdir_mtime_new != stat_info.st_mtime) {
400 md->mdir_mtime_new = stat_info.st_mtime;
401 changed = 1;
402 }
403
404 /* did cur/ changed ? */
405
406 r = stat(path_cur, &stat_info);
407 if (r < 0) {
408 res = MAILDIR_ERROR_DIRECTORY;
409 goto free;
410 }
411
412 if (md->mdir_mtime_cur != stat_info.st_mtime) {
413 md->mdir_mtime_cur = stat_info.st_mtime;
414 changed = 1;
415 }
416
417 if (changed) {
418
419 carray_set_size(md->mdir_msg_list, 0);
420 chash_clear(md->mdir_msg_hash);
421
422 maildir_flush(md, 1);
423
424 /* messages in new */
425 r = add_directory(md, path_new, 1);
426 if (r != MAILDIR_NO_ERROR) {
427 res = r;
428 goto free;
429 }
430
431 maildir_flush(md, 0);
432
433 /* messages in cur */
434 r = add_directory(md, path_cur, 0);
435 if (r != MAILDIR_NO_ERROR) {
436 res = r;
437 goto free;
438 }
439 }
440
441 snprintf(path_maildirfolder, sizeof(path_maildirfolder),
442 "%s/maildirfolder", md->mdir_path);
443
444 if (stat(path_maildirfolder, &stat_info) == -1) {
445 int fd;
446
447 fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR);
448 if (fd != -1)
449 close(fd);
450 }
451
452 return MAILDIR_NO_ERROR;
453
454 free:
455 maildir_flush(md, 0);
456 maildir_flush(md, 1);
457 md->mdir_mtime_cur = (time_t) -1;
458 md->mdir_mtime_new = (time_t) -1;
459 return res;
460}
461
462#ifndef LIBETPAN_SYSTEM_BASENAME
463static char * libetpan_basename(char * filename)
464{
465 char * next;
466 char * p;
467
468 p = filename;
469 next = strchr(p, '/');
470
471 while (next != NULL) {
472 p = next;
473 next = strchr(p + 1, '/');
474 }
475
476 if (p == filename)
477 return filename;
478 else
479 return p + 1;
480}
481#else
482#define libetpan_basename(a) basename(a)
483#endif
484
485int maildir_message_add_uid(struct maildir * md,
486 const char * message, size_t size,
487 char * uid, size_t max_uid_len)
488{
489 char path_new[PATH_MAX];
490 char tmpname[PATH_MAX];
491 int fd;
492 int r;
493 char * mapping;
494 char * delivery_tmp_name;
495 char * delivery_tmp_basename;
496 char delivery_new_name[PATH_MAX];
497 char * delivery_new_basename;
498 int res;
499 struct stat stat_info;
500
501 r = maildir_update(md);
502 if (r != MAILDIR_NO_ERROR) {
503 res = r;
504 goto err;
505 }
506
507 /* write to tmp/ with a classic temporary file */
508
509 snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX",
510 md->mdir_path);
511 fd = mkstemp(tmpname);
512 if (fd < 0) {
513 res = MAILDIR_ERROR_FILE;
514 goto err;
515 }
516
517 r = ftruncate(fd, size);
518 if (r < 0) {
519 res = MAILDIR_ERROR_FILE;
520 goto close;
521 }
522
523 mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
524 if (mapping == MAP_FAILED) {
525 res = MAILDIR_ERROR_FILE;
526 goto close;
527 }
528
529 memcpy(mapping, message, size);
530
531 msync(mapping, size, MS_SYNC);
532 munmap(mapping, size);
533
534 close(fd);
535
536 /* write to tmp/ with maildir standard name */
537
538 delivery_tmp_name = maildir_get_new_message_filename(md, tmpname);
539 if (delivery_tmp_name == NULL) {
540 res = MAILDIR_ERROR_FILE;
541 goto unlink;
542 }
543
544 /* write to new/ with maildir standard name */
545
546 strncpy(tmpname, delivery_tmp_name, sizeof(tmpname));
547 tmpname[sizeof(tmpname) - 1] = '\0';
548
549 delivery_tmp_basename = libetpan_basename(tmpname);
550
551 snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s",
552 md->mdir_path, delivery_tmp_basename);
553
554 r = link(delivery_tmp_name, delivery_new_name);
555 if (r == 0) {
556 unlink(delivery_tmp_name);
557 }
558 else if (errno == EXDEV) {
559 res = MAILDIR_ERROR_FOLDER;
560 goto unlink_tmp;
561 }
562 else if (errno == EPERM) {
563 r = rename(delivery_tmp_name, delivery_new_name);
564 if (r < 0) {
565 res = MAILDIR_ERROR_FILE;
566 goto unlink_tmp;
567 }
568 }
569
570 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
571 r = stat(path_new, &stat_info);
572 if (r < 0) {
573 unlink(delivery_new_name);
574 res = MAILDIR_ERROR_FILE;
575 goto unlink_tmp;
576 }
577
578 md->mdir_mtime_new = stat_info.st_mtime;
579
580 delivery_new_basename = libetpan_basename(delivery_new_name);
581
582 r = add_message(md, delivery_new_basename, 1);
583 if (r != MAILDIR_NO_ERROR) {
584 unlink(delivery_new_name);
585 res = MAILDIR_ERROR_FILE;
586 goto unlink_tmp;
587 }
588
589 if (uid != NULL)
590 strncpy(uid, delivery_new_basename, max_uid_len);
591
592 free(delivery_tmp_name);
593
594 return MAILDIR_NO_ERROR;
595
596 unlink_tmp:
597 unlink(delivery_tmp_name);
598 free(delivery_tmp_name);
599 goto err;
600 close:
601 close(fd);
602 unlink:
603 unlink(tmpname);
604 err:
605 return res;
606}
607
608int maildir_message_add(struct maildir * md,
609 const char * message, size_t size)
610{
611 return maildir_message_add_uid(md, message, size,
612 NULL, 0);
613}
614
615int maildir_message_add_file_uid(struct maildir * md, int fd,
616 char * uid, size_t max_uid_len)
617{
618 char * message;
619 struct stat buf;
620 int r;
621
622 if (fstat(fd, &buf) == -1)
623 return MAILDIR_ERROR_FILE;
624
625 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
626 if (message == MAP_FAILED)
627 return MAILDIR_ERROR_FILE;
628
629 r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len);
630
631 munmap(message, buf.st_size);
632
633 return r;
634}
635
636int maildir_message_add_file(struct maildir * md, int fd)
637{
638 return maildir_message_add_file_uid(md, fd,
639 NULL, 0);
640}
641
642char * maildir_message_get(struct maildir * md, const char * uid)
643{
644 chashdatum key;
645 chashdatum value;
646 char filename[PATH_MAX];
647 char * dup_filename;
648 struct maildir_msg * msg;
649 char * dir;
650 int r;
651
652 key.data = (void *) uid;
653 key.len = strlen(uid);
654 r = chash_get(md->mdir_msg_hash, &key, &value);
655 if (r < 0)
656 return NULL;
657
658 msg = value.data;
659 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
660 dir = "new";
661 else
662 dir = "cur";
663
664 snprintf(filename, sizeof(filename), "%s/%s/%s",
665 md->mdir_path, dir, msg->msg_filename);
666
667 dup_filename = strdup(filename);
668 if (dup_filename == NULL)
669 return NULL;
670
671 return dup_filename;
672}
673
674int maildir_message_remove(struct maildir * md, const char * uid)
675{
676 chashdatum key;
677 chashdatum value;
678 char filename[PATH_MAX];
679 struct maildir_msg * msg;
680 char * dir;
681 int r;
682 int res;
683
684 key.data = (void *) uid;
685 key.len = strlen(uid);
686 r = chash_get(md->mdir_msg_hash, &key, &value);
687 if (r < 0) {
688 res = MAILDIR_ERROR_NOT_FOUND;
689 goto err;
690 }
691
692 msg = value.data;
693 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
694 dir = "new";
695 else
696 dir = "cur";
697
698 snprintf(filename, sizeof(filename), "%s/%s/%s",
699 md->mdir_path, dir, msg->msg_filename);
700
701 r = unlink(filename);
702 if (r < 0) {
703 res = MAILDIR_ERROR_FILE;
704 goto err;
705 }
706
707 return MAILDIR_NO_ERROR;
708
709 err:
710 return res;
711}
712
713int maildir_message_change_flags(struct maildir * md,
714 const char * uid, int new_flags)
715{
716 chashdatum key;
717 chashdatum value;
718 char filename[PATH_MAX];
719 struct maildir_msg * msg;
720 char * dir;
721 int r;
722 char new_filename[PATH_MAX];
723 char flag_str[5];
724 size_t i;
725 int res;
726
727 key.data = (void *) uid;
728 key.len = strlen(uid);
729 r = chash_get(md->mdir_msg_hash, &key, &value);
730 if (r < 0) {
731 res = MAILDIR_ERROR_NOT_FOUND;
732 goto err;
733 }
734
735 msg = value.data;
736 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
737 dir = "new";
738 else
739 dir = "cur";
740
741 snprintf(filename, sizeof(filename), "%s/%s/%s",
742 md->mdir_path, dir, msg->msg_filename);
743
744 if ((new_flags & MAILDIR_FLAG_NEW) != 0)
745 dir = "new";
746 else
747 dir = "cur";
748
749 i = 0;
750 if ((new_flags & MAILDIR_FLAG_SEEN) != 0) {
751 flag_str[i] = 'S';
752 i ++;
753 }
754 if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) {
755 flag_str[i] = 'R';
756 i ++;
757 }
758 if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) {
759 flag_str[i] = 'F';
760 i ++;
761 }
762 if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) {
763 flag_str[i] = 'T';
764 i ++;
765 }
766 flag_str[i] = 0;
767
768 if (flag_str[0] == '\0')
769 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s",
770 md->mdir_path, dir, msg->msg_uid);
771 else
772 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s",
773 md->mdir_path, dir, msg->msg_uid, flag_str);
774
775 if (strcmp(filename, new_filename) == 0)
776 return MAILDIR_NO_ERROR;
777
778 r = link(filename, new_filename);
779 if (r == 0) {
780 unlink(filename);
781 }
782 else if (errno == EXDEV) {
783 res = MAILDIR_ERROR_FOLDER;
784 goto err;
785 }
786 else if (errno == EPERM) {
787 r = rename(filename, new_filename);
788 if (r < 0) {
789 res = MAILDIR_ERROR_FOLDER;
790 goto err;
791 }
792 }
793
794 return MAILDIR_NO_ERROR;
795
796 err:
797 return res;
798}
diff --git a/libetpan/src/low-level/maildir/maildir.h b/libetpan/src/low-level/maildir/maildir.h
new file mode 100644
index 0000000..d099dc0
--- a/dev/null
+++ b/libetpan/src/low-level/maildir/maildir.h
@@ -0,0 +1,67 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIR_H
37
38#define MAILDIR_H
39
40#include <libetpan/maildir_types.h>
41
42struct maildir * maildir_new(const char * path);
43
44void maildir_free(struct maildir * md);
45
46int maildir_update(struct maildir * md);
47
48int maildir_message_add_uid(struct maildir * md,
49 const char * message, size_t size,
50 char * uid, size_t max_uid_len);
51
52int maildir_message_add(struct maildir * md,
53 const char * message, size_t size);
54
55int maildir_message_add_file_uid(struct maildir * md, int fd,
56 char * uid, size_t max_uid_len);
57
58int maildir_message_add_file(struct maildir * md, int fd);
59
60char * maildir_message_get(struct maildir * md, const char * uid);
61
62int maildir_message_remove(struct maildir * md, const char * uid);
63
64int maildir_message_change_flags(struct maildir * md,
65 const char * uid, int new_flags);
66
67#endif
diff --git a/libetpan/src/low-level/maildir/maildir_types.h b/libetpan/src/low-level/maildir/maildir_types.h
new file mode 100644
index 0000000..5be5a78
--- a/dev/null
+++ b/libetpan/src/low-level/maildir/maildir_types.h
@@ -0,0 +1,91 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILDIR_TYPES_H
37
38#define MAILDIR_TYPES_H
39
40#include <sys/types.h>
41#include <unistd.h>
42#include <libetpan/chash.h>
43#include <libetpan/carray.h>
44#include <inttypes.h>
45
46#include <libetpan/libetpan-config.h>
47
48#define LIBETPAN_MAILDIR
49
50enum {
51 MAILDIR_NO_ERROR = 0,
52 MAILDIR_ERROR_CREATE,
53 MAILDIR_ERROR_DIRECTORY,
54 MAILDIR_ERROR_MEMORY,
55 MAILDIR_ERROR_FILE,
56 MAILDIR_ERROR_NOT_FOUND,
57 MAILDIR_ERROR_FOLDER,
58};
59
60#define MAILDIR_FLAG_NEW (1 << 0)
61#define MAILDIR_FLAG_SEEN (1 << 1)
62#define MAILDIR_FLAG_REPLIED (1 << 2)
63#define MAILDIR_FLAG_FLAGGED (1 << 3)
64#define MAILDIR_FLAG_TRASHED (1 << 4)
65
66struct maildir_msg {
67 char * msg_uid;
68 char * msg_filename;
69 int msg_flags;
70};
71
72/*
73 work around for missing #define HOST_NAME_MAX in Linux
74*/
75
76#ifndef HOST_NAME_MAX
77#define HOST_NAME_MAX 255
78#endif
79
80struct maildir {
81 pid_t mdir_pid;
82 char mdir_hostname[HOST_NAME_MAX];
83 char mdir_path[PATH_MAX];
84 uint32_t mdir_counter;
85 time_t mdir_mtime_new;
86 time_t mdir_mtime_cur;
87 carray * mdir_msg_list;
88 chash * mdir_msg_hash;
89};
90
91#endif
diff --git a/libetpan/src/low-level/mbox/TODO b/libetpan/src/low-level/mbox/TODO
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/TODO
diff --git a/libetpan/src/low-level/mbox/mailmbox.c b/libetpan/src/low-level/mbox/mailmbox.c
new file mode 100644
index 0000000..9937f3a
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox.c
@@ -0,0 +1,1525 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmbox.h"
37
38#include <sys/file.h>
39#include <sys/stat.h>
40#include <unistd.h>
41#include <sys/mman.h>
42#include <fcntl.h>
43#include <time.h>
44#include <sys/types.h>
45#include <unistd.h>
46
47#include <string.h>
48#include <ctype.h>
49#include <stdlib.h>
50#include <stdio.h>
51
52#include "libetpan-config.h"
53
54#include "mmapstring.h"
55#include "mailmbox_parse.h"
56#include "maillock.h"
57
58/*
59 http://www.qmail.org/qmail-manual-html/man5/mbox.html
60 RFC 2076
61*/
62
63#define TMPDIR "/tmp"
64
65/* mbox is a file with a corresponding filename */
66
67#define UID_HEADER "X-LibEtPan-UID:"
68
69#ifndef TRUE
70#define TRUE 1
71#endif
72
73#ifndef FALSE
74#define FALSE 0
75#endif
76
77int mailmbox_write_lock(struct mailmbox_folder * folder)
78{
79 int r;
80
81 if (folder->mb_read_only)
82 return MAILMBOX_ERROR_READONLY;
83
84 r = maillock_write_lock(folder->mb_filename, folder->mb_fd);
85 if (r == 0)
86 return MAILMBOX_NO_ERROR;
87 else
88 return MAILMBOX_ERROR_FILE;
89}
90
91int mailmbox_write_unlock(struct mailmbox_folder * folder)
92{
93 int r;
94
95 r = maillock_write_unlock(folder->mb_filename, folder->mb_fd);
96 if (r == 0)
97 return MAILMBOX_NO_ERROR;
98 else
99 return MAILMBOX_ERROR_FILE;
100}
101
102int mailmbox_read_lock(struct mailmbox_folder * folder)
103{
104 int r;
105
106 r = maillock_read_lock(folder->mb_filename, folder->mb_fd);
107 if (r == 0)
108 return MAILMBOX_NO_ERROR;
109 else
110 return MAILMBOX_ERROR_FILE;
111}
112
113int mailmbox_read_unlock(struct mailmbox_folder * folder)
114{
115 int r;
116
117 r = maillock_read_unlock(folder->mb_filename, folder->mb_fd);
118 if (r == 0)
119 return MAILMBOX_NO_ERROR;
120 else
121 return MAILMBOX_ERROR_FILE;
122}
123
124
125/*
126 map the file into memory.
127 the file must be locked.
128*/
129
130int mailmbox_map(struct mailmbox_folder * folder)
131{
132 char * str;
133 struct stat buf;
134 int res;
135 int r;
136
137 r = stat(folder->mb_filename, &buf);
138 if (r < 0) {
139 res = MAILMBOX_ERROR_FILE;
140 goto err;
141 }
142
143 if (folder->mb_read_only)
144 str = (char *) mmap(0, buf.st_size, PROT_READ,
145 MAP_PRIVATE, folder->mb_fd, 0);
146 else
147 str = (char *) mmap(0, buf.st_size, PROT_READ | PROT_WRITE,
148 MAP_SHARED, folder->mb_fd, 0);
149 if (str == MAP_FAILED) {
150 res = MAILMBOX_ERROR_FILE;
151 goto err;
152 }
153
154 folder->mb_mapping = str;
155 folder->mb_mapping_size = buf.st_size;
156
157 return MAILMBOX_NO_ERROR;
158
159 err:
160 return res;
161}
162
163/*
164 unmap the file
165*/
166
167void mailmbox_unmap(struct mailmbox_folder * folder)
168{
169 munmap(folder->mb_mapping, folder->mb_mapping_size);
170 folder->mb_mapping = NULL;
171 folder->mb_mapping_size = 0;
172}
173
174void mailmbox_sync(struct mailmbox_folder * folder)
175{
176 msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC);
177}
178
179void mailmbox_timestamp(struct mailmbox_folder * folder)
180{
181 int r;
182 struct stat buf;
183
184 r = stat(folder->mb_filename, &buf);
185 if (r < 0)
186 folder->mb_mtime = (time_t) -1;
187 else
188 folder->mb_mtime = buf.st_mtime;
189}
190
191/*
192 open the file
193*/
194
195int mailmbox_open(struct mailmbox_folder * folder)
196{
197 int fd;
198 int read_only;
199
200 fd = -1;
201 read_only = TRUE;
202
203 if (!folder->mb_read_only) {
204 read_only = FALSE;
205 fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
206 }
207
208 if (folder->mb_read_only || (fd < 0)) {
209 read_only = TRUE;
210 fd = open(folder->mb_filename, O_RDONLY);
211 if (fd < 0)
212 return MAILMBOX_ERROR_FILE_NOT_FOUND;
213 }
214
215 folder->mb_fd = fd;
216 folder->mb_read_only = read_only;
217
218 return MAILMBOX_NO_ERROR;
219}
220
221/*
222 close the file
223*/
224
225void mailmbox_close(struct mailmbox_folder * folder)
226{
227 close(folder->mb_fd);
228 folder->mb_fd = -1;
229}
230
231
232static int mailmbox_validate_lock(struct mailmbox_folder * folder,
233 int (* custom_lock)(struct mailmbox_folder *),
234 int (* custom_unlock)(struct mailmbox_folder *))
235{
236 struct stat buf;
237 int res;
238 int r;
239
240 r = stat(folder->mb_filename, &buf);
241 if (r < 0) {
242 buf.st_mtime = (time_t) -1;
243 }
244
245 if ((buf.st_mtime != folder->mb_mtime) ||
246 ((size_t) buf.st_size != folder->mb_mapping_size)) {
247 int r;
248
249 mailmbox_unmap(folder);
250 mailmbox_close(folder);
251
252 r = mailmbox_open(folder);
253 if (r != MAILMBOX_NO_ERROR) {
254 res = r;
255 goto err;
256 }
257
258 r = custom_lock(folder);
259 if (r != MAILMBOX_NO_ERROR) {
260 res = r;
261 goto err;
262 }
263
264 r = mailmbox_map(folder);
265 if (r != MAILMBOX_NO_ERROR) {
266 res = r;
267 goto err_unlock;
268 }
269
270 r = mailmbox_parse(folder);
271 if (r != MAILMBOX_NO_ERROR) {
272 res = r;
273 goto err_unlock;
274 }
275
276 folder->mb_mtime = buf.st_mtime;
277
278 return MAILMBOX_NO_ERROR;
279 }
280 else {
281 r = custom_lock(folder);
282 if (r != MAILMBOX_NO_ERROR) {
283 res = r;
284 goto err;
285 }
286 }
287
288 return MAILMBOX_NO_ERROR;
289
290 err_unlock:
291 custom_unlock(folder);
292 err:
293 return res;
294}
295
296
297int mailmbox_validate_write_lock(struct mailmbox_folder * folder)
298{
299 return mailmbox_validate_lock(folder,
300 mailmbox_write_lock,
301 mailmbox_write_unlock);
302}
303
304
305int mailmbox_validate_read_lock(struct mailmbox_folder * folder)
306{
307 return mailmbox_validate_lock(folder,
308 mailmbox_read_lock,
309 mailmbox_read_unlock);
310}
311
312
313/* ********************************************************************** */
314/* append messages */
315
316#define MAX_FROM_LINE_SIZE 256
317
318static inline size_t get_line(const char * line, size_t length,
319 const char ** pnext_line, size_t * pcount)
320{
321 size_t count;
322
323 count = 0;
324
325 while (1) {
326 if (length == 0)
327 break;
328
329 if (* line == '\r') {
330 line ++;
331
332 count ++;
333 length --;
334
335 if (length > 0) {
336 if (* line == '\n') {
337 line ++;
338
339 count ++;
340 length --;
341
342 break;
343 }
344 }
345 }
346 else if (* line == '\n') {
347 line ++;
348
349 count ++;
350 length --;
351
352 break;
353 }
354 else {
355 line ++;
356 length --;
357 count ++;
358 }
359 }
360
361 * pnext_line = line;
362 * pcount = count;
363
364 return count;
365}
366
367/*
368 TODO : should strip \r\n if any
369 see also in write_fixed_line
370*/
371
372static inline size_t get_fixed_line_size(const char * line, size_t length,
373 const char ** pnext_line, size_t * pcount,
374 size_t * pfixed_count)
375{
376 size_t count;
377 const char * next_line;
378 size_t fixed_count;
379
380 if (!get_line(line, length, &next_line, &count))
381 return 0;
382
383 fixed_count = count;
384 if (count >= 5) {
385 if (line[0] == 'F') {
386 if (strncmp(line, "From ", 5) == 0)
387 fixed_count ++;
388 }
389 }
390
391 * pnext_line = next_line;
392 * pcount = count;
393 * pfixed_count = fixed_count;
394
395 return count;
396}
397
398static size_t get_fixed_message_size(const char * message, size_t size,
399 uint32_t uid, int force_no_uid)
400{
401 size_t fixed_size;
402 size_t cur_token;
403 size_t left;
404 const char * next;
405 const char * cur;
406 int end;
407 int r;
408 uint32_t tmp_uid;
409
410 cur_token = 0;
411
412 fixed_size = 0;
413
414 /* headers */
415
416 end = FALSE;
417 while (!end) {
418 size_t begin;
419 int ignore;
420
421 ignore = FALSE;
422 begin = cur_token;
423 if (cur_token + strlen(UID_HEADER) <= size) {
424 if (message[cur_token] == 'X') {
425 if (strncasecmp(message + cur_token, UID_HEADER,
426 strlen(UID_HEADER)) == 0) {
427 ignore = TRUE;
428 }
429 }
430 }
431
432 r = mailimf_ignore_field_parse(message, size, &cur_token);
433 switch (r) {
434 case MAILIMF_NO_ERROR:
435 if (!ignore)
436 fixed_size += cur_token - begin;
437 break;
438 case MAILIMF_ERROR_PARSE:
439 default:
440 end = TRUE;
441 break;
442 }
443 }
444
445 if (!force_no_uid) {
446 /* UID header */
447
448 fixed_size += strlen(UID_HEADER " \r\n");
449
450 tmp_uid = uid;
451 while (tmp_uid >= 10) {
452 tmp_uid /= 10;
453 fixed_size ++;
454 }
455 fixed_size ++;
456 }
457
458 /* body */
459
460 left = size - cur_token;
461 next = message + cur_token;
462 while (left > 0) {
463 size_t count;
464 size_t fixed_count;
465
466 cur = next;
467
468 if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count))
469 break;
470
471 fixed_size += fixed_count;
472 left -= count;
473 }
474
475 return fixed_size;
476}
477
478static inline char * write_fixed_line(char * str,
479 const char * line, size_t length,
480 const char ** pnext_line, size_t * pcount)
481{
482 size_t count;
483 const char * next_line;
484
485 if (!get_line(line, length, &next_line, &count))
486 return str;
487
488 if (count >= 5) {
489 if (line[0] == 'F') {
490 if (strncmp(line, "From ", 5) == 0) {
491 * str = '>';
492 str ++;
493 }
494 }
495 }
496
497 memcpy(str, line, count);
498
499 * pnext_line = next_line;
500 * pcount = count;
501 str += count;
502
503 return str;
504}
505
506static char * write_fixed_message(char * str,
507 const char * message, size_t size,
508 uint32_t uid, int force_no_uid)
509{
510 size_t fixed_size;
511 size_t cur_token;
512 size_t left;
513 int end;
514 int r;
515 const char * cur_src;
516 size_t numlen;
517
518 cur_token = 0;
519
520 fixed_size = 0;
521
522 /* headers */
523
524 end = FALSE;
525 while (!end) {
526 size_t begin;
527 int ignore;
528
529 ignore = FALSE;
530 begin = cur_token;
531 if (cur_token + strlen(UID_HEADER) <= size) {
532 if (message[cur_token] == 'X') {
533 if (strncasecmp(message + cur_token, UID_HEADER,
534 strlen(UID_HEADER)) == 0) {
535 ignore = TRUE;
536 }
537 }
538 }
539
540 r = mailimf_ignore_field_parse(message, size, &cur_token);
541 switch (r) {
542 case MAILIMF_NO_ERROR:
543 if (!ignore) {
544 memcpy(str, message + begin, cur_token - begin);
545 str += cur_token - begin;
546 }
547 break;
548 case MAILIMF_ERROR_PARSE:
549 default:
550 end = TRUE;
551 break;
552 }
553 }
554
555 if (!force_no_uid) {
556 /* UID header */
557
558 memcpy(str, UID_HEADER " ", strlen(UID_HEADER " "));
559 str += strlen(UID_HEADER " ");
560 numlen = snprintf(str, 20, "%i\r\n", uid);
561 str += numlen;
562 }
563
564 /* body */
565
566 cur_src = message + cur_token;
567 left = size - cur_token;
568 while (left > 0) {
569 size_t count;
570 const char * next;
571
572 str = write_fixed_line(str, cur_src, left, &next, &count);
573
574 cur_src = next;
575 left -= count;
576 }
577
578 return str;
579}
580
581#define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n"
582
583int
584mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder,
585 carray * append_tab)
586{
587 size_t extra_size;
588 int r;
589 char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE;
590 struct tm time_info;
591 time_t date;
592 int res;
593 size_t old_size;
594 char * str;
595 unsigned int i;
596 size_t from_size;
597 size_t maxuid;
598 size_t left;
599 size_t crlf_count;
600
601 if (folder->mb_read_only) {
602 res = MAILMBOX_ERROR_READONLY;
603 goto err;
604 }
605
606 date = time(NULL);
607 from_size = strlen(DEFAULT_FROM_LINE);
608 if (localtime_r(&date, &time_info) != NULL)
609 from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info);
610
611 maxuid = /* */ folder->mb_max_uid;
612
613 extra_size = 0;
614 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
615 struct mailmbox_append_info * info;
616
617 info = carray_get(append_tab, i);
618 extra_size += from_size;
619 extra_size += get_fixed_message_size(info->ai_message, info->ai_size,
620 folder->mb_max_uid + i + 1,
621 folder->mb_no_uid);
622 extra_size += 2; /* CR LF */
623
624 info->ai_uid = folder->mb_max_uid + i + 1;
625 }
626
627 left = folder->mb_mapping_size;
628 crlf_count = 0;
629 while (left >= 1) {
630 if (folder->mb_mapping[left - 1] == '\n') {
631 crlf_count ++;
632 left --;
633 }
634 else if (folder->mb_mapping[left - 1] == '\r') {
635 left --;
636 }
637 else
638 break;
639
640 if (crlf_count == 2)
641 break;
642 }
643
644 old_size = folder->mb_mapping_size;
645 mailmbox_unmap(folder);
646
647 if (old_size != 0) {
648 if (crlf_count != 2)
649 extra_size += (2 - crlf_count) * 2;
650 }
651
652 r = ftruncate(folder->mb_fd, extra_size + old_size);
653 if (r < 0) {
654 mailmbox_map(folder);
655 res = MAILMBOX_ERROR_FILE;
656 goto err;
657 }
658
659 r = mailmbox_map(folder);
660 if (r < 0) {
661 ftruncate(folder->mb_fd, old_size);
662 return MAILMBOX_ERROR_FILE;
663 }
664
665 str = folder->mb_mapping + old_size;
666
667 if (old_size != 0) {
668 for(i = 0 ; i < 2 - crlf_count ; i ++) {
669 * str = '\r';
670 str ++;
671 * str = '\n';
672 str ++;
673 }
674 }
675
676 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
677 struct mailmbox_append_info * info;
678
679 info = carray_get(append_tab, i);
680
681 memcpy(str, from_line, from_size);
682
683 str += strlen(from_line);
684
685 str = write_fixed_message(str, info->ai_message, info->ai_size,
686 folder->mb_max_uid + i + 1,
687 folder->mb_no_uid);
688
689 * str = '\r';
690 str ++;
691 * str = '\n';
692 str ++;
693 }
694
695 folder->mb_max_uid += carray_count(append_tab);
696
697 return MAILMBOX_NO_ERROR;
698
699 err:
700 return res;
701}
702
703int
704mailmbox_append_message_list(struct mailmbox_folder * folder,
705 carray * append_tab)
706{
707 int r;
708 int res;
709 size_t cur_token;
710
711 r = mailmbox_validate_write_lock(folder);
712 if (r != MAILMBOX_NO_ERROR) {
713 res = r;
714 goto err;
715 }
716
717 r = mailmbox_expunge_no_lock(folder);
718 if (r != MAILMBOX_NO_ERROR) {
719 res = r;
720 goto unlock;
721 }
722
723 cur_token = folder->mb_mapping_size;
724
725 r = mailmbox_append_message_list_no_lock(folder, append_tab);
726 if (r != MAILMBOX_NO_ERROR) {
727 res = r;
728 goto unlock;
729 }
730
731 mailmbox_sync(folder);
732
733 r = mailmbox_parse_additionnal(folder, &cur_token);
734 if (r != MAILMBOX_NO_ERROR) {
735 res = r;
736 goto unlock;
737 }
738
739 mailmbox_timestamp(folder);
740
741 mailmbox_write_unlock(folder);
742
743 return MAILMBOX_NO_ERROR;
744
745 unlock:
746 mailmbox_write_unlock(folder);
747 err:
748 return res;
749}
750
751int
752mailmbox_append_message_uid(struct mailmbox_folder * folder,
753 const char * data, size_t len, unsigned int * puid)
754{
755 carray * tab;
756 struct mailmbox_append_info * append_info;
757 int res;
758 int r;
759
760 tab = carray_new(1);
761 if (tab == NULL) {
762 res = MAILMBOX_ERROR_MEMORY;
763 goto err;
764 }
765
766 append_info = mailmbox_append_info_new(data, len);
767 if (append_info == NULL) {
768 res = MAILMBOX_ERROR_MEMORY;
769 goto free_list;
770 }
771
772 r = carray_add(tab, append_info, NULL);
773 if (r < 0) {
774 res = MAILMBOX_ERROR_MEMORY;
775 goto free_append_info;
776 }
777
778 r = mailmbox_append_message_list(folder, tab);
779
780 if (puid != NULL)
781 * puid = append_info->ai_uid;
782
783 mailmbox_append_info_free(append_info);
784 carray_free(tab);
785
786 return r;
787
788 free_append_info:
789 mailmbox_append_info_free(append_info);
790 free_list:
791 carray_free(tab);
792 err:
793 return res;
794}
795
796int
797mailmbox_append_message(struct mailmbox_folder * folder,
798 const char * data, size_t len)
799{
800 return mailmbox_append_message_uid(folder, data, len, NULL);
801}
802
803/* ********************************************************************** */
804
805int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder,
806 uint32_t num, char ** result,
807 size_t * result_len)
808{
809 struct mailmbox_msg_info * info;
810 int res;
811 chashdatum key;
812 chashdatum data;
813 int r;
814
815 key.data = &num;
816 key.len = sizeof(num);
817
818 r = chash_get(folder->mb_hash, &key, &data);
819 if (r < 0) {
820 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
821 goto err;
822 }
823
824 info = data.data;
825
826 if (info->msg_deleted) {
827 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
828 goto err;
829 }
830
831 * result = folder->mb_mapping + info->msg_headers;
832 * result_len = info->msg_size - info->msg_start_len;
833
834 return MAILMBOX_NO_ERROR;
835
836 err:
837 return res;
838}
839
840int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder,
841 uint32_t num, char ** result,
842 size_t * result_len)
843{
844 struct mailmbox_msg_info * info;
845 int res;
846 chashdatum key;
847 chashdatum data;
848 int r;
849
850 key.data = &num;
851 key.len = sizeof(num);
852
853 r = chash_get(folder->mb_hash, &key, &data);
854 if (r < 0) {
855 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
856 goto err;
857 }
858
859 info = data.data;
860
861 if (info->msg_deleted) {
862 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
863 goto err;
864 }
865
866 * result = folder->mb_mapping + info->msg_headers;
867 * result_len = info->msg_headers_len;
868
869 return MAILMBOX_NO_ERROR;
870
871 err:
872 return res;
873}
874
875int mailmbox_fetch_msg(struct mailmbox_folder * folder,
876 uint32_t num, char ** result,
877 size_t * result_len)
878{
879 MMAPString * mmapstr;
880 int res;
881 char * data;
882 size_t len;
883 int r;
884 size_t fixed_size;
885 char * end;
886
887 r = mailmbox_validate_read_lock(folder);
888 if (r != MAILMBOX_NO_ERROR) {
889 res = r;
890 goto err;
891 }
892
893 r = mailmbox_fetch_msg_no_lock(folder, num, &data, &len);
894 if (r != MAILMBOX_NO_ERROR) {
895 res = r;
896 goto unlock;
897 }
898
899 /* size with no uid */
900 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
901
902#if 0
903 mmapstr = mmap_string_new_len(data, fixed_size);
904 if (mmapstr == NULL) {
905 res = MAILMBOX_ERROR_MEMORY;
906 goto unlock;
907 }
908#endif
909 mmapstr = mmap_string_sized_new(fixed_size);
910 if (mmapstr == NULL) {
911 res = MAILMBOX_ERROR_MEMORY;
912 goto unlock;
913 }
914
915 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
916 * end = '\0';
917 mmapstr->len = fixed_size;
918
919 r = mmap_string_ref(mmapstr);
920 if (r < 0) {
921 mmap_string_free(mmapstr);
922 res = MAILMBOX_ERROR_MEMORY;
923 goto unlock;
924 }
925
926 * result = mmapstr->str;
927 * result_len = mmapstr->len;
928
929 mailmbox_read_unlock(folder);
930
931 return MAILMBOX_NO_ERROR;
932
933 unlock:
934 mailmbox_read_unlock(folder);
935 err:
936 return res;
937}
938
939int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder,
940 uint32_t num, char ** result,
941 size_t * result_len)
942{
943 MMAPString * mmapstr;
944 int res;
945 char * data;
946 size_t len;
947 int r;
948 size_t fixed_size;
949 char * end;
950
951 r = mailmbox_validate_read_lock(folder);
952 if (r != MAILMBOX_NO_ERROR) {
953 res = r;
954 goto err;
955 }
956
957 r = mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len);
958 if (r != MAILMBOX_NO_ERROR) {
959 res = r;
960 goto unlock;
961 }
962
963#if 0
964 mmapstr = mmap_string_new_len(data, len);
965 if (mmapstr == NULL) {
966 res = MAILMBOX_ERROR_MEMORY;
967 goto unlock;
968 }
969#endif
970 /* size with no uid */
971 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
972
973 mmapstr = mmap_string_sized_new(fixed_size);
974 if (mmapstr == NULL) {
975 res = MAILMBOX_ERROR_MEMORY;
976 goto unlock;
977 }
978
979 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
980 * end = '\0';
981 mmapstr->len = fixed_size;
982
983 r = mmap_string_ref(mmapstr);
984 if (r < 0) {
985 mmap_string_free(mmapstr);
986 res = MAILMBOX_ERROR_MEMORY;
987 goto unlock;
988 }
989
990 * result = mmapstr->str;
991 * result_len = mmapstr->len;
992
993 mailmbox_read_unlock(folder);
994
995 return MAILMBOX_NO_ERROR;
996
997 unlock:
998 mailmbox_read_unlock(folder);
999 err:
1000 return res;
1001}
1002
1003void mailmbox_fetch_result_free(char * msg)
1004{
1005 mmap_string_unref(msg);
1006}
1007
1008
1009int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder,
1010 struct mailmbox_folder * src_folder,
1011 carray * tab)
1012{
1013 int r;
1014 int res;
1015 carray * append_tab;
1016 unsigned int i;
1017
1018 r = mailmbox_validate_read_lock(src_folder);
1019 if (r != MAILMBOX_NO_ERROR) {
1020 res = r;
1021 goto err;
1022 }
1023
1024 append_tab = carray_new(carray_count(tab));
1025 if (append_tab == NULL) {
1026 res = MAILMBOX_ERROR_MEMORY;
1027 goto src_unlock;
1028 }
1029
1030 for(i = 0 ; i < carray_count(tab) ; i ++) {
1031 struct mailmbox_append_info * append_info;
1032 char * data;
1033 size_t len;
1034 uint32_t uid;
1035
1036 uid = * ((uint32_t *) carray_get(tab, i));
1037
1038 r = mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len);
1039 if (r != MAILMBOX_NO_ERROR) {
1040 res = r;
1041 goto free_list;
1042 }
1043
1044 append_info = mailmbox_append_info_new(data, len);
1045 if (append_info == NULL) {
1046 res = MAILMBOX_ERROR_MEMORY;
1047 goto free_list;
1048 }
1049
1050 r = carray_add(append_tab, append_info, NULL);
1051 if (r < 0) {
1052 mailmbox_append_info_free(append_info);
1053 res = MAILMBOX_ERROR_MEMORY;
1054 goto free_list;
1055 }
1056 }
1057
1058 r = mailmbox_append_message_list(dest_folder, append_tab);
1059 if (r != MAILMBOX_NO_ERROR) {
1060 res = r;
1061 goto src_unlock;
1062 }
1063
1064 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1065 struct mailmbox_append_info * append_info;
1066
1067 append_info = carray_get(append_tab, i);
1068 mailmbox_append_info_free(append_info);
1069 }
1070 carray_free(append_tab);
1071
1072 mailmbox_read_unlock(src_folder);
1073
1074 return MAILMBOX_NO_ERROR;
1075
1076 free_list:
1077 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1078 struct mailmbox_append_info * append_info;
1079
1080 append_info = carray_get(append_tab, i);
1081 mailmbox_append_info_free(append_info);
1082 }
1083 carray_free(append_tab);
1084 src_unlock:
1085 mailmbox_read_unlock(src_folder);
1086 err:
1087 return res;
1088}
1089
1090int mailmbox_copy_msg(struct mailmbox_folder * dest_folder,
1091 struct mailmbox_folder * src_folder,
1092 uint32_t uid)
1093{
1094 carray * tab;
1095 int res;
1096 uint32_t * puid;
1097 int r;
1098
1099 tab = carray_new(1);
1100 if (tab == NULL) {
1101 res = MAILMBOX_ERROR_MEMORY;
1102 goto err;
1103 }
1104
1105 puid = malloc(sizeof(* puid));
1106 if (puid == NULL) {
1107 res = MAILMBOX_ERROR_MEMORY;
1108 goto free_array;
1109 }
1110 * puid = uid;
1111
1112 r = mailmbox_copy_msg_list(dest_folder, src_folder, tab);
1113 res = r;
1114
1115 free(puid);
1116 free_array:
1117 carray_free(tab);
1118 err:
1119 return res;
1120}
1121
1122static int mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd,
1123 struct mailmbox_folder * folder,
1124 size_t * result_size)
1125{
1126 int r;
1127 int res;
1128 unsigned long i;
1129 size_t cur_offset;
1130 char * dest;
1131 size_t size;
1132
1133 size = 0;
1134 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1135 struct mailmbox_msg_info * info;
1136
1137 info = carray_get(folder->mb_tab, i);
1138
1139 if (!info->msg_deleted) {
1140 size += info->msg_size + info->msg_padding;
1141
1142 if (!folder->mb_no_uid) {
1143 if (!info->msg_written_uid) {
1144 uint32_t uid;
1145
1146 size += strlen(UID_HEADER " \r\n");
1147
1148 uid = info->msg_uid;
1149 while (uid >= 10) {
1150 uid /= 10;
1151 size ++;
1152 }
1153 size ++;
1154 }
1155 }
1156 }
1157 }
1158
1159 r = ftruncate(dest_fd, size);
1160 if (r < 0) {
1161 res = MAILMBOX_ERROR_FILE;
1162 goto err;
1163 }
1164
1165 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0);
1166 if (dest == MAP_FAILED) {
1167 res = MAILMBOX_ERROR_FILE;
1168 goto err;
1169 }
1170
1171 cur_offset = 0;
1172 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1173 struct mailmbox_msg_info * info;
1174
1175 info = carray_get(folder->mb_tab, i);
1176
1177 if (!info->msg_deleted) {
1178 memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start,
1179 info->msg_headers_len + info->msg_start_len);
1180 cur_offset += info->msg_headers_len + info->msg_start_len;
1181
1182 if (!folder->mb_no_uid) {
1183 if (!info->msg_written_uid) {
1184 size_t numlen;
1185
1186 memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " "));
1187 cur_offset += strlen(UID_HEADER " ");
1188 numlen = snprintf(dest + cur_offset, size - cur_offset,
1189 "%i\r\n", info->msg_uid);
1190 cur_offset += numlen;
1191 }
1192 }
1193
1194 memcpy(dest + cur_offset,
1195 folder->mb_mapping + info->msg_headers + info->msg_headers_len,
1196 info->msg_size - (info->msg_start_len + info->msg_headers_len)
1197 + info->msg_padding);
1198
1199 cur_offset += info->msg_size -
1200 (info->msg_start_len + info->msg_headers_len)
1201 + info->msg_padding;
1202 }
1203 }
1204 fflush(stdout);
1205
1206 msync(dest, size, MS_SYNC);
1207 munmap(dest, size);
1208
1209 * result_size = size;
1210
1211 return MAILMBOX_NO_ERROR;
1212
1213 err:
1214 return res;
1215}
1216
1217static int copy_to_old_file(char * source_filename,
1218 char * destination_filename, size_t size)
1219{
1220 int source_fd;
1221 int dest_fd;
1222 char * source;
1223 char * dest;
1224 int res;
1225 int r;
1226
1227 source_fd = open(source_filename, O_RDONLY);
1228 if (source_fd < 0) {
1229 res = MAILMBOX_ERROR_FILE;
1230 goto err;
1231 }
1232
1233 source = (char *) mmap(0, size, PROT_READ, MAP_PRIVATE, source_fd, 0);
1234 if (source == MAP_FAILED) {
1235 res = MAILMBOX_ERROR_FILE;
1236 goto close_source;
1237 }
1238
1239 dest_fd = open(destination_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1240 if (dest_fd < 0) {
1241 res = MAILMBOX_ERROR_FILE;
1242 goto unmap_source;
1243 }
1244
1245 r = ftruncate(dest_fd, size);
1246 if (r < 0) {
1247 res = MAILMBOX_ERROR_FILE;
1248 goto close_dest;
1249 }
1250
1251 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE,
1252 MAP_SHARED, dest_fd, 0);
1253 if (dest == MAP_FAILED) {
1254 res = MAILMBOX_ERROR_FILE;
1255 goto close_dest;
1256 }
1257
1258 memcpy(dest, source, size);
1259
1260 munmap(dest, size);
1261 close(source_fd);
1262 munmap(source, size);
1263 close(source_fd);
1264
1265 return MAILMBOX_NO_ERROR;
1266
1267 unmap_dest:
1268 munmap(dest, size);
1269 close_dest:
1270 close(source_fd);
1271 unmap_source:
1272 munmap(source, size);
1273 close_source:
1274 close(source_fd);
1275 err:
1276 return res;
1277}
1278
1279int mailmbox_expunge_no_lock(struct mailmbox_folder * folder)
1280{
1281 char tmpfile[PATH_MAX];
1282 int r;
1283 int res;
1284 int dest_fd;
1285 size_t size;
1286 mode_t old_mask;
1287
1288 if (folder->mb_read_only)
1289 return MAILMBOX_ERROR_READONLY;
1290
1291 if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
1292 (!folder->mb_changed)) {
1293 /* no need to expunge */
1294 return MAILMBOX_NO_ERROR;
1295 }
1296
1297 snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename);
1298 old_mask = umask(0077);
1299 dest_fd = mkstemp(tmpfile);
1300 umask(old_mask);
1301
1302 if (dest_fd < 0) {
1303 /* fallback to tmp dir */
1304
1305 snprintf(tmpfile, PATH_MAX, TMPDIR "/etpan-unsafe-XXXXXX");
1306
1307 old_mask = umask(0077);
1308 dest_fd = mkstemp(tmpfile);
1309 umask(old_mask);
1310
1311 if (dest_fd < 0) {
1312 res = MAILMBOX_ERROR_FILE;
1313 goto err;
1314 }
1315 }
1316
1317 r = mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd,
1318 folder, &size);
1319 if (r != MAILMBOX_NO_ERROR) {
1320 res = r;
1321 goto unlink;
1322 }
1323
1324 close(dest_fd);
1325
1326 r = rename(tmpfile, folder->mb_filename);
1327 if (r < 0) {
1328 mailmbox_unmap(folder);
1329 mailmbox_close(folder);
1330
1331 /* fallback on copy to old file */
1332
1333 r = copy_to_old_file(tmpfile, folder->mb_filename, size);
1334 if (r != MAILMBOX_NO_ERROR) {
1335 res = r;
1336 goto err;
1337 }
1338
1339 unlink(tmpfile);
1340 }
1341 else {
1342 mailmbox_unmap(folder);
1343 mailmbox_close(folder);
1344 }
1345
1346 r = mailmbox_open(folder);
1347 if (r != MAILMBOX_NO_ERROR) {
1348 res = r;
1349 goto err;
1350 }
1351
1352 r = mailmbox_map(folder);
1353 if (r != MAILMBOX_NO_ERROR) {
1354 res = r;
1355 goto err;
1356 }
1357
1358 r = mailmbox_parse(folder);
1359 if (r != MAILMBOX_NO_ERROR) {
1360 res = r;
1361 goto err;
1362 }
1363
1364 mailmbox_timestamp(folder);
1365
1366 folder->mb_changed = FALSE;
1367 folder->mb_deleted_count = 0;
1368
1369 return MAILMBOX_NO_ERROR;
1370
1371 unlink:
1372 close(dest_fd);
1373 unlink(tmpfile);
1374 err:
1375 return res;
1376}
1377
1378int mailmbox_expunge(struct mailmbox_folder * folder)
1379{
1380 int r;
1381 int res;
1382
1383 r = mailmbox_validate_write_lock(folder);
1384 if (r != MAILMBOX_NO_ERROR) {
1385 res = r;
1386 goto err;
1387 }
1388
1389 r = mailmbox_expunge_no_lock(folder);
1390 res = r;
1391
1392 mailmbox_write_unlock(folder);
1393 err:
1394 return res;
1395}
1396
1397int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid)
1398{
1399 struct mailmbox_msg_info * info;
1400 int res;
1401 chashdatum key;
1402 chashdatum data;
1403 int r;
1404
1405 if (folder->mb_read_only) {
1406 res = MAILMBOX_ERROR_READONLY;
1407 goto err;
1408 }
1409
1410 key.data = &uid;
1411 key.len = sizeof(uid);
1412
1413 r = chash_get(folder->mb_hash, &key, &data);
1414 if (r < 0) {
1415 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1416 goto err;
1417 }
1418
1419 info = data.data;
1420
1421 if (info->msg_deleted) {
1422 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1423 goto err;
1424 }
1425
1426 info->msg_deleted = TRUE;
1427 folder->mb_changed = TRUE;
1428 folder->mb_deleted_count ++;
1429
1430 return MAILMBOX_NO_ERROR;
1431
1432 err:
1433 return res;
1434}
1435
1436
1437/*
1438 INIT of MBOX
1439
1440 - open file
1441 - map the file
1442
1443 - lock the file
1444
1445 - parse memory
1446
1447 - unlock the file
1448*/
1449
1450int mailmbox_init(const char * filename,
1451 int force_readonly,
1452 int force_no_uid,
1453 uint32_t default_written_uid,
1454 struct mailmbox_folder ** result_folder)
1455{
1456 struct mailmbox_folder * folder;
1457 int r;
1458 int res;
1459
1460 folder = mailmbox_folder_new(filename);
1461 if (folder == NULL) {
1462 res = MAILMBOX_ERROR_MEMORY;
1463 goto err;
1464 }
1465 folder->mb_no_uid = force_no_uid;
1466 folder->mb_read_only = force_readonly;
1467 folder->mb_written_uid = default_written_uid;
1468
1469 folder->mb_changed = FALSE;
1470 folder->mb_deleted_count = 0;
1471
1472 r = mailmbox_open(folder);
1473 if (r != MAILMBOX_NO_ERROR) {
1474 res = r;
1475 goto free;
1476 }
1477
1478 r = mailmbox_map(folder);
1479 if (r != MAILMBOX_NO_ERROR) {
1480 res = r;
1481 goto close;
1482 }
1483
1484 r = mailmbox_validate_read_lock(folder);
1485 if (r != MAILMBOX_NO_ERROR) {
1486 res = r;
1487 goto unmap;
1488 }
1489
1490 mailmbox_read_unlock(folder);
1491
1492 * result_folder = folder;
1493
1494 return MAILMBOX_NO_ERROR;
1495
1496 unmap:
1497 mailmbox_unmap(folder);
1498 close:
1499 mailmbox_close(folder);
1500 free:
1501 mailmbox_folder_free(folder);
1502 err:
1503 return res;
1504}
1505
1506
1507/*
1508 when MBOX is DONE
1509
1510 - check for changes
1511
1512 - unmap the file
1513 - close file
1514*/
1515
1516void mailmbox_done(struct mailmbox_folder * folder)
1517{
1518 if (!folder->mb_read_only)
1519 mailmbox_expunge(folder);
1520
1521 mailmbox_unmap(folder);
1522 mailmbox_close(folder);
1523
1524 mailmbox_folder_free(folder);
1525}
diff --git a/libetpan/src/low-level/mbox/mailmbox.h b/libetpan/src/low-level/mbox/mailmbox.h
new file mode 100644
index 0000000..ea21d48
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMBOX_H
37
38#define MAILMBOX_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmbox_types.h>
45
46int
47mailmbox_append_message_list(struct mailmbox_folder * folder,
48 carray * append_tab);
49
50int
51mailmbox_append_message(struct mailmbox_folder * folder,
52 const char * data, size_t len);
53
54int
55mailmbox_append_message_uid(struct mailmbox_folder * folder,
56 const char * data, size_t len, unsigned int * puid);
57
58int mailmbox_fetch_msg(struct mailmbox_folder * folder,
59 uint32_t num, char ** result,
60 size_t * result_len);
61
62int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder,
63 uint32_t num, char ** result,
64 size_t * result_len);
65
66void mailmbox_fetch_result_free(char * msg);
67
68int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder,
69 struct mailmbox_folder * src_folder,
70 carray * tab);
71
72int mailmbox_copy_msg(struct mailmbox_folder * dest_folder,
73 struct mailmbox_folder * src_folder,
74 uint32_t uid);
75
76int mailmbox_expunge(struct mailmbox_folder * folder);
77
78int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid);
79
80int mailmbox_init(const char * filename,
81 int force_readonly,
82 int force_no_uid,
83 uint32_t default_written_uid,
84 struct mailmbox_folder ** result_folder);
85
86void mailmbox_done(struct mailmbox_folder * folder);
87
88/* low-level access primitives */
89
90int mailmbox_write_lock(struct mailmbox_folder * folder);
91
92int mailmbox_write_unlock(struct mailmbox_folder * folder);
93
94int mailmbox_read_lock(struct mailmbox_folder * folder);
95
96int mailmbox_read_unlock(struct mailmbox_folder * folder);
97
98
99/* memory map */
100
101int mailmbox_map(struct mailmbox_folder * folder);
102
103void mailmbox_unmap(struct mailmbox_folder * folder);
104
105void mailmbox_sync(struct mailmbox_folder * folder);
106
107
108/* open & close file */
109
110int mailmbox_open(struct mailmbox_folder * folder);
111
112void mailmbox_close(struct mailmbox_folder * folder);
113
114
115/* validate cache */
116
117int mailmbox_validate_write_lock(struct mailmbox_folder * folder);
118
119int mailmbox_validate_read_lock(struct mailmbox_folder * folder);
120
121
122/* fetch message */
123
124int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder,
125 uint32_t num, char ** result,
126 size_t * result_len);
127
128int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder,
129 uint32_t num, char ** result,
130 size_t * result_len);
131
132/* append message */
133
134int
135mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder,
136 carray * append_tab);
137
138int mailmbox_expunge_no_lock(struct mailmbox_folder * folder);
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/src/low-level/mbox/mailmbox_parse.c b/libetpan/src/low-level/mbox/mailmbox_parse.c
new file mode 100644
index 0000000..65642ac
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_parse.c
@@ -0,0 +1,620 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmbox_parse.h"
37
38#include "mailmbox.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <string.h>
43#include <stdlib.h>
44
45#define UID_HEADER "X-LibEtPan-UID:"
46
47#ifndef TRUE
48#define TRUE 1
49#endif
50
51#ifndef FALSE
52#define FALSE 0
53#endif
54
55enum {
56 UNSTRUCTURED_START,
57 UNSTRUCTURED_CR,
58 UNSTRUCTURED_LF,
59 UNSTRUCTURED_WSP,
60 UNSTRUCTURED_OUT
61};
62
63static inline int
64mailmbox_fields_parse(char * str, size_t length,
65 size_t * index,
66 uint32_t * puid,
67 size_t * phlen)
68{
69 size_t cur_token;
70 int r;
71 size_t hlen;
72 size_t uid;
73 int end;
74
75 cur_token = * index;
76
77 end = FALSE;
78 uid = 0;
79 while (!end) {
80 size_t begin;
81
82 begin = cur_token;
83
84 r = mailimf_ignore_field_parse(str, length, &cur_token);
85 switch (r) {
86 case MAILIMF_NO_ERROR:
87 if (str[begin] == 'X') {
88
89 if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
90 begin += strlen(UID_HEADER);
91
92 while (str[begin] == ' ')
93 begin ++;
94
95 uid = strtoul(str + begin, NULL, 10);
96 }
97 }
98
99 break;
100 case MAILIMF_ERROR_PARSE:
101 default:
102 end = TRUE;
103 break;
104 }
105 }
106
107 hlen = cur_token - * index;
108
109 * phlen = hlen;
110 * puid = uid;
111 * index = cur_token;
112
113 return MAILMBOX_NO_ERROR;
114}
115
116enum {
117 IN_MAIL,
118 FIRST_CR,
119 FIRST_LF,
120 SECOND_CR,
121 SECOND_LF,
122 PARSING_F,
123 PARSING_R,
124 PARSING_O,
125 PARSING_M,
126 OUT_MAIL
127};
128
129
130
131
132static inline int
133mailmbox_single_parse(char * str, size_t length,
134 size_t * index,
135 size_t * pstart,
136 size_t * pstart_len,
137 size_t * pheaders,
138 size_t * pheaders_len,
139 size_t * pbody,
140 size_t * pbody_len,
141 size_t * psize,
142 size_t * ppadding,
143 uint32_t * puid)
144{
145 size_t cur_token;
146 size_t start;
147 size_t start_len;
148 size_t headers;
149 size_t headers_len;
150 size_t body;
151 size_t end;
152 size_t next;
153 size_t message_length;
154 uint32_t uid;
155 int r;
156#if 0
157 int in_mail_data;
158#endif
159#if 0
160 size_t begin;
161#endif
162
163 int state;
164
165 cur_token = * index;
166
167 if (cur_token >= length)
168 return MAILMBOX_ERROR_PARSE;
169
170 start = cur_token;
171 start_len = 0;
172 headers = cur_token;
173
174 if (cur_token + 5 < length) {
175 if (strncmp(str + cur_token, "From ", 5) == 0) {
176 cur_token += 5;
177 while (str[cur_token] != '\n') {
178 cur_token ++;
179 if (cur_token >= length)
180 break;
181 }
182 if (cur_token < length) {
183 cur_token ++;
184 headers = cur_token;
185 start_len = headers - start;
186 }
187 }
188 }
189
190 next = length;
191
192 r = mailmbox_fields_parse(str, length, &cur_token,
193 &uid, &headers_len);
194 if (r != MAILMBOX_NO_ERROR)
195 return r;
196
197 /* save position */
198#if 0
199 begin = cur_token;
200#endif
201
202 mailimf_crlf_parse(str, length, &cur_token);
203
204#if 0
205 if (str[cur_token] == 'F') {
206 printf("start !\n");
207 printf("%50.50s\n", str + cur_token);
208 getchar();
209 }
210#endif
211
212 body = cur_token;
213
214 /* restore position */
215 /* cur_token = begin; */
216
217 state = FIRST_LF;
218
219 end = length;
220
221#if 0
222 in_mail_data = 0;
223#endif
224 while (state != OUT_MAIL) {
225
226 if (cur_token >= length) {
227 if (state == IN_MAIL)
228 end = length;
229 next = length;
230 break;
231 }
232
233 switch(state) {
234 case IN_MAIL:
235 switch(str[cur_token]) {
236 case '\r':
237 state = FIRST_CR;
238 break;
239 case '\n':
240 state = FIRST_LF;
241 break;
242 case 'F':
243 if (cur_token == body) {
244 end = cur_token;
245 next = cur_token;
246 state = PARSING_F;
247 }
248 break;
249#if 0
250 default:
251 in_mail_data = 1;
252 break;
253#endif
254 }
255 break;
256
257 case FIRST_CR:
258 end = cur_token;
259 switch(str[cur_token]) {
260 case '\r':
261 state = SECOND_CR;
262 break;
263 case '\n':
264 state = FIRST_LF;
265 break;
266 default:
267 state = IN_MAIL;
268#if 0
269 in_mail_data = 1;
270#endif
271 break;
272 }
273 break;
274
275 case FIRST_LF:
276 end = cur_token;
277 switch(str[cur_token]) {
278 case '\r':
279 state = SECOND_CR;
280 break;
281 case '\n':
282 state = SECOND_LF;
283 break;
284 default:
285 state = IN_MAIL;
286#if 0
287 in_mail_data = 1;
288#endif
289 break;
290 }
291 break;
292
293 case SECOND_CR:
294 switch(str[cur_token]) {
295 case '\r':
296 end = cur_token;
297 break;
298 case '\n':
299 state = SECOND_LF;
300 break;
301 case 'F':
302 next = cur_token;
303 state = PARSING_F;
304 break;
305 default:
306 state = IN_MAIL;
307#if 0
308 in_mail_data = 1;
309#endif
310 break;
311 }
312 break;
313
314 case SECOND_LF:
315 switch(str[cur_token]) {
316 case '\r':
317 state = SECOND_CR;
318 break;
319 case '\n':
320 end = cur_token;
321 break;
322 case 'F':
323 next = cur_token;
324 state = PARSING_F;
325 break;
326 default:
327 state = IN_MAIL;
328#if 0
329 in_mail_data = 1;
330#endif
331 break;
332 }
333 break;
334
335 case PARSING_F:
336 switch(str[cur_token]) {
337 case 'r':
338 state = PARSING_R;
339 break;
340 default:
341 state = IN_MAIL;
342#if 0
343 in_mail_data = 1;
344#endif
345 break;
346 }
347 break;
348
349 case PARSING_R:
350 switch(str[cur_token]) {
351 case 'o':
352 state = PARSING_O;
353 break;
354 default:
355 state = IN_MAIL;
356#if 0
357 in_mail_data = 1;
358#endif
359 break;
360 }
361 break;
362
363 case PARSING_O:
364 switch(str[cur_token]) {
365 case 'm':
366 state = PARSING_M;
367 break;
368 default:
369 state = IN_MAIL;
370#if 0
371 in_mail_data = 1;
372#endif
373 break;
374 }
375 break;
376
377 case PARSING_M:
378 switch(str[cur_token]) {
379 case ' ':
380 state = OUT_MAIL;
381 break;
382 default:
383 state = IN_MAIL;
384 break;
385 }
386 break;
387 }
388
389 cur_token ++;
390 }
391
392 message_length = end - start;
393
394 * pstart = start;
395 * pstart_len = start_len;
396 * pheaders = headers;
397 * pheaders_len = headers_len;
398 * pbody = body;
399 * pbody_len = end - body;
400 * psize = message_length;
401 * ppadding = next - end;
402 * puid = uid;
403
404 * index = next;
405
406 return MAILMBOX_NO_ERROR;
407}
408
409
410int
411mailmbox_parse_additionnal(struct mailmbox_folder * folder,
412 size_t * index)
413{
414 size_t cur_token;
415
416 size_t start;
417 size_t start_len;
418 size_t headers;
419 size_t headers_len;
420 size_t body;
421 size_t body_len;
422 size_t size;
423 size_t padding;
424 uint32_t uid;
425 int r;
426 int res;
427
428 uint32_t max_uid;
429 uint32_t first_index;
430 unsigned int i;
431 unsigned int j;
432
433 cur_token = * index;
434
435 /* remove temporary UID that we will parse */
436
437 first_index = carray_count(folder->mb_tab);
438
439 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
440 struct mailmbox_msg_info * info;
441
442 info = carray_get(folder->mb_tab, i);
443
444 if (info->msg_start < cur_token) {
445 continue;
446 }
447
448 if (!info->msg_written_uid) {
449 chashdatum key;
450
451 key.data = &info->msg_uid;
452 key.len = sizeof(info->msg_uid);
453
454 chash_delete(folder->mb_hash, &key, NULL);
455 carray_delete_fast(folder->mb_tab, i);
456 mailmbox_msg_info_free(info);
457 if (i < first_index)
458 first_index = i;
459 }
460 }
461
462 /* make a sequence in the table */
463
464 max_uid = folder->mb_written_uid;
465
466 i = 0;
467 j = 0;
468 while (i < carray_count(folder->mb_tab)) {
469 struct mailmbox_msg_info * info;
470
471 info = carray_get(folder->mb_tab, i);
472 if (info != NULL) {
473 carray_set(folder->mb_tab, j, info);
474
475 if (info->msg_uid > max_uid)
476 max_uid = info->msg_uid;
477
478 info->msg_index = j;
479 j ++;
480 }
481 i ++;
482 }
483 carray_set_size(folder->mb_tab, j);
484
485 /* parse content */
486
487 first_index = j;
488
489 while (1) {
490 struct mailmbox_msg_info * info;
491 chashdatum key;
492 chashdatum data;
493
494 r = mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size,
495 &cur_token,
496 &start, &start_len,
497 &headers, &headers_len,
498 &body, &body_len,
499 &size, &padding, &uid);
500 if (r == MAILMBOX_NO_ERROR) {
501 /* do nothing */
502 }
503 else if (r == MAILMBOX_ERROR_PARSE)
504 break;
505 else {
506 res = r;
507 goto err;
508 }
509
510 key.data = &uid;
511 key.len = sizeof(uid);
512
513 r = chash_get(folder->mb_hash, &key, &data);
514 if (r == 0) {
515 info = data.data;
516
517 if (!info->msg_written_uid) {
518 /* some new mail has been written and override an
519 existing temporary UID */
520
521 chash_delete(folder->mb_hash, &key, NULL);
522 info->msg_uid = 0;
523
524 if (info->msg_index < first_index)
525 first_index = info->msg_index;
526 }
527 else
528 uid = 0;
529 }
530
531 if (uid > max_uid)
532 max_uid = uid;
533
534 r = mailmbox_msg_info_update(folder,
535 start, start_len, headers, headers_len,
536 body, body_len, size, padding, uid);
537 if (r != MAILMBOX_NO_ERROR) {
538 res = r;
539 goto err;
540 }
541 }
542
543 * index = cur_token;
544
545 folder->mb_written_uid = max_uid;
546
547 /* attribute uid */
548
549 for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) {
550 struct mailmbox_msg_info * info;
551 chashdatum key;
552 chashdatum data;
553
554 info = carray_get(folder->mb_tab, i);
555
556 if (info->msg_uid != 0) {
557 continue;
558 }
559
560 max_uid ++;
561 info->msg_uid = max_uid;
562
563 key.data = &info->msg_uid;
564 key.len = sizeof(info->msg_uid);
565 data.data = info;
566 data.len = 0;
567
568 r = chash_set(folder->mb_hash, &key, &data, NULL);
569 if (r < 0) {
570 res = MAILMBOX_ERROR_MEMORY;
571 goto err;
572 }
573 }
574
575 folder->mb_max_uid = max_uid;
576
577 return MAILMBOX_NO_ERROR;
578
579 err:
580 return res;
581}
582
583static void flush_uid(struct mailmbox_folder * folder)
584{
585 unsigned int i;
586
587 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
588 struct mailmbox_msg_info * info;
589
590 info = carray_get(folder->mb_tab, i);
591 if (info != NULL)
592 mailmbox_msg_info_free(info);
593 }
594
595 chash_clear(folder->mb_hash);
596 carray_set_size(folder->mb_tab, 0);
597}
598
599int mailmbox_parse(struct mailmbox_folder * folder)
600{
601 int r;
602 int res;
603 size_t cur_token;
604
605 flush_uid(folder);
606
607 cur_token = 0;
608
609 r = mailmbox_parse_additionnal(folder, &cur_token);
610
611 if (r != MAILMBOX_NO_ERROR) {
612 res = r;
613 goto err;
614 }
615
616 return MAILMBOX_NO_ERROR;
617
618 err:
619 return res;
620}
diff --git a/libetpan/src/low-level/mbox/mailmbox_parse.h b/libetpan/src/low-level/mbox/mailmbox_parse.h
new file mode 100644
index 0000000..6b533a9
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_parse.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMBOX_PARSE_H
37
38#define MAILMBOX_PARSE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailmbox_types.h"
45
46int mailmbox_parse(struct mailmbox_folder * folder);
47
48int
49mailmbox_parse_additionnal(struct mailmbox_folder * folder,
50 size_t * index);
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/low-level/mbox/mailmbox_types.c b/libetpan/src/low-level/mbox/mailmbox_types.c
new file mode 100644
index 0000000..aaf76dc
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_types.c
@@ -0,0 +1,251 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmbox_types.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#ifndef TRUE
42#define TRUE 1
43#endif
44
45#ifndef FALSE
46#define FALSE 0
47#endif
48
49/* *********************************************************************** */
50
51int mailmbox_msg_info_update(struct mailmbox_folder * folder,
52 size_t msg_start, size_t msg_start_len,
53 size_t msg_headers, size_t msg_headers_len,
54 size_t msg_body, size_t msg_body_len,
55 size_t msg_size, size_t msg_padding,
56 uint32_t msg_uid)
57{
58 struct mailmbox_msg_info * info;
59 int res;
60 chashdatum key;
61 chashdatum data;
62 int r;
63
64 key.data = &msg_uid;
65 key.len = sizeof(msg_uid);
66 r = chash_get(folder->mb_hash, &key, &data);
67 if (r < 0) {
68 unsigned int index;
69
70 info = mailmbox_msg_info_new(msg_start, msg_start_len,
71 msg_headers, msg_headers_len,
72 msg_body, msg_body_len, msg_size, msg_padding, msg_uid);
73 if (info == NULL) {
74 res = MAILMBOX_ERROR_MEMORY;
75 goto err;
76 }
77
78 r = carray_add(folder->mb_tab, info, &index);
79 if (r < 0) {
80 mailmbox_msg_info_free(info);
81 res = MAILMBOX_ERROR_MEMORY;
82 goto err;
83 }
84
85 if (msg_uid != 0) {
86 chashdatum key;
87 chashdatum data;
88
89 key.data = &msg_uid;
90 key.len = sizeof(msg_uid);
91 data.data = info;
92 data.len = 0;
93
94 r = chash_set(folder->mb_hash, &key, &data, NULL);
95 if (r < 0) {
96 mailmbox_msg_info_free(info);
97 carray_delete(folder->mb_tab, index);
98 res = MAILMBOX_ERROR_MEMORY;
99 goto err;
100 }
101 }
102
103 info->msg_index = index;
104 }
105 else {
106 info = data.data;
107
108 info->msg_start = msg_start;
109 info->msg_start_len = msg_start_len;
110 info->msg_headers = msg_headers;
111 info->msg_headers_len = msg_headers_len;
112 info->msg_body = msg_body;
113 info->msg_body_len = msg_body_len;
114 info->msg_size = msg_size;
115 info->msg_padding = msg_padding;
116 }
117
118 return MAILMBOX_NO_ERROR;
119
120 err:
121 return res;
122}
123
124
125struct mailmbox_msg_info *
126mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
127 size_t msg_headers, size_t msg_headers_len,
128 size_t msg_body, size_t msg_body_len,
129 size_t msg_size, size_t msg_padding,
130 uint32_t msg_uid)
131{
132 struct mailmbox_msg_info * info;
133
134 info = malloc(sizeof(* info));
135 if (info == NULL)
136 return NULL;
137
138 info->msg_index = 0;
139 info->msg_uid = msg_uid;
140 if (msg_uid != 0)
141 info->msg_written_uid = TRUE;
142 else
143 info->msg_written_uid = FALSE;
144 info->msg_deleted = FALSE;
145
146 info->msg_start = msg_start;
147 info->msg_start_len = msg_start_len;
148
149 info->msg_headers = msg_headers;
150 info->msg_headers_len = msg_headers_len;
151
152 info->msg_body = msg_body;
153 info->msg_body_len = msg_body_len;
154
155 info->msg_size = msg_size;
156
157 info->msg_padding = msg_padding;
158
159 return info;
160}
161
162void mailmbox_msg_info_free(struct mailmbox_msg_info * info)
163{
164 free(info);
165}
166
167
168/* append info */
169
170struct mailmbox_append_info *
171mailmbox_append_info_new(const char * ai_message, size_t ai_size)
172{
173 struct mailmbox_append_info * info;
174
175 info = malloc(sizeof(* info));
176 if (info == NULL)
177 return NULL;
178
179 info->ai_message = ai_message;
180 info->ai_size = ai_size;
181 info->ai_uid = 0;
182
183 return info;
184}
185
186void mailmbox_append_info_free(struct mailmbox_append_info * info)
187{
188 free(info);
189}
190
191struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename)
192{
193 struct mailmbox_folder * folder;
194
195 folder = malloc(sizeof(* folder));
196 if (folder == NULL)
197 goto err;
198
199 strncpy(folder->mb_filename, mb_filename, PATH_MAX);
200
201 folder->mb_mtime = (time_t) -1;
202
203 folder->mb_fd = -1;
204 folder->mb_read_only = TRUE;
205 folder->mb_no_uid = TRUE;
206
207 folder->mb_changed = FALSE;
208 folder->mb_deleted_count = 0;
209
210 folder->mb_mapping = NULL;
211 folder->mb_mapping_size = 0;
212
213 folder->mb_written_uid = 0;
214 folder->mb_max_uid = 0;
215
216 folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
217 if (folder->mb_hash == NULL)
218 goto free;
219
220 folder->mb_tab = carray_new(128);
221 if (folder->mb_tab == NULL)
222 goto free_hash;
223
224 return folder;
225
226 free_hash:
227 chash_free(folder->mb_hash);
228 free:
229 free(folder);
230 err:
231 return NULL;
232}
233
234void mailmbox_folder_free(struct mailmbox_folder * folder)
235{
236 unsigned int i;
237
238 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
239 struct mailmbox_msg_info * info;
240
241 info = carray_get(folder->mb_tab, i);
242 if (info != NULL)
243 mailmbox_msg_info_free(info);
244 }
245
246 carray_free(folder->mb_tab);
247
248 chash_free(folder->mb_hash);
249
250 free(folder);
251}
diff --git a/libetpan/src/low-level/mbox/mailmbox_types.h b/libetpan/src/low-level/mbox/mailmbox_types.h
new file mode 100644
index 0000000..4ce241d
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_types.h
@@ -0,0 +1,143 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMBOX_TYPES_H
37
38#define MAILMBOX_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45
46#include <libetpan/libetpan-config.h>
47
48#include <libetpan/mailimf.h>
49#include <libetpan/carray.h>
50#include <libetpan/chash.h>
51
52enum {
53 MAILMBOX_NO_ERROR = 0,
54 MAILMBOX_ERROR_PARSE,
55 MAILMBOX_ERROR_INVAL,
56 MAILMBOX_ERROR_FILE_NOT_FOUND,
57 MAILMBOX_ERROR_MEMORY,
58 MAILMBOX_ERROR_TEMPORARY_FILE,
59 MAILMBOX_ERROR_FILE,
60 MAILMBOX_ERROR_MSG_NOT_FOUND,
61 MAILMBOX_ERROR_READONLY,
62};
63
64
65struct mailmbox_folder {
66 char mb_filename[PATH_MAX];
67
68 time_t mb_mtime;
69
70 int mb_fd;
71 int mb_read_only;
72 int mb_no_uid;
73
74 int mb_changed;
75 unsigned int mb_deleted_count;
76
77 char * mb_mapping;
78 size_t mb_mapping_size;
79
80 uint32_t mb_written_uid;
81 uint32_t mb_max_uid;
82
83 chash * mb_hash;
84 carray * mb_tab;
85};
86
87struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename);
88void mailmbox_folder_free(struct mailmbox_folder * folder);
89
90
91struct mailmbox_msg_info {
92 unsigned int msg_index;
93 uint32_t msg_uid;
94 int msg_written_uid;
95 int msg_deleted;
96
97 size_t msg_start;
98 size_t msg_start_len;
99
100 size_t msg_headers;
101 size_t msg_headers_len;
102
103 size_t msg_body;
104 size_t msg_body_len;
105
106 size_t msg_size;
107
108 size_t msg_padding;
109};
110
111
112int mailmbox_msg_info_update(struct mailmbox_folder * folder,
113 size_t msg_start, size_t msg_start_len,
114 size_t msg_headers, size_t msg_headers_len,
115 size_t msg_body, size_t msg_body_len,
116 size_t msg_size, size_t msg_padding,
117 uint32_t msg_uid);
118
119struct mailmbox_msg_info *
120mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
121 size_t msg_headers, size_t msg_headers_len,
122 size_t msg_body, size_t msg_body_len,
123 size_t msg_size, size_t msg_padding,
124 uint32_t msg_uid);
125
126void mailmbox_msg_info_free(struct mailmbox_msg_info * info);
127
128struct mailmbox_append_info {
129 const char * ai_message;
130 size_t ai_size;
131 unsigned int ai_uid;
132};
133
134struct mailmbox_append_info *
135mailmbox_append_info_new(const char * ai_message, size_t ai_size);
136
137void mailmbox_append_info_free(struct mailmbox_append_info * info);
138
139#ifdef __cplusplus
140}
141#endif
142
143#endif
diff --git a/libetpan/src/low-level/mh/mailmh.c b/libetpan/src/low-level/mh/mailmh.c
new file mode 100644
index 0000000..42cab9d
--- a/dev/null
+++ b/libetpan/src/low-level/mh/mailmh.c
@@ -0,0 +1,989 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmh.h"
37
38/*
39perfs :
40
41/net/home/dinh/Mail/inbox/sylpheed 686
42
432724 /net/home/dinh/Mail/inbox/sylpheed
44
45bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null
46
47real 0m0.385s
48user 0m0.270s
49sys 0m0.110s
50
51*/
52
53#include <dirent.h>
54#include <sys/stat.h>
55#include <errno.h>
56#include <unistd.h>
57#include <sys/mman.h>
58#include <fcntl.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62
63#include "libetpan-config.h"
64
65struct mailmh * mailmh_new(const char * foldername)
66{
67 struct mailmh * f;
68
69 f = malloc(sizeof(*f));
70 if (f == NULL)
71 return NULL;
72
73 f->mh_main = mailmh_folder_new(NULL, foldername);
74 if (f->mh_main == NULL) {
75 free(f);
76 return NULL;
77 }
78
79 return f;
80}
81
82void mailmh_free(struct mailmh * f)
83{
84 mailmh_folder_free(f->mh_main);
85 free(f);
86}
87
88
89
90struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size,
91 time_t mtime)
92{
93 struct mailmh_msg_info * msg_info;
94
95 msg_info = malloc(sizeof(* msg_info));
96 if (msg_info == NULL)
97 return NULL;
98 msg_info->msg_index = index;
99 msg_info->msg_size = size;
100 msg_info->msg_mtime = mtime;
101
102 msg_info->msg_array_index = 0;
103
104 return msg_info;
105}
106
107void mailmh_msg_info_free(struct mailmh_msg_info * msg_info)
108{
109 free(msg_info);
110}
111
112struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent,
113 const char * name)
114{
115 char * filename;
116 char * parent_filename;
117
118 struct mailmh_folder * folder;
119
120 folder = malloc(sizeof(* folder));
121 if (folder == NULL)
122 goto err;
123
124 if (parent == NULL) {
125 filename = strdup(name);
126 if (filename == NULL)
127 goto free_folder;
128 }
129 else {
130 parent_filename = parent->fl_filename;
131 filename = malloc(strlen(parent_filename) + strlen(name) + 2);
132 if (filename == NULL)
133 goto free_folder;
134
135 strcpy(filename, parent_filename);
136 strcat(filename, MAIL_DIR_SEPARATOR_S);
137 strcat(filename, name);
138 }
139
140 folder->fl_filename = filename;
141
142 folder->fl_name = strdup(name);
143 if (folder->fl_name == NULL)
144 goto free_filename;
145
146 folder->fl_msgs_tab = carray_new(128);
147 if (folder->fl_msgs_tab == NULL)
148 goto free_name;
149
150#if 0
151 folder->fl_msgs_hash = cinthash_new(128);
152 if (folder->fl_msgs_hash == NULL)
153 goto free_msgs_tab;
154#endif
155 folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
156 if (folder->fl_msgs_hash == NULL)
157 goto free_msgs_tab;
158
159 folder->fl_subfolders_tab = carray_new(128);
160 if (folder->fl_subfolders_tab == NULL)
161 goto free_msgs_hash;
162
163 folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE);
164 if (folder->fl_subfolders_hash == NULL)
165 goto free_subfolders_tab;
166
167 folder->fl_mtime = 0;
168 folder->fl_parent = parent;
169 folder->fl_max_index = 0;
170
171 return folder;
172
173 free_subfolders_tab:
174 carray_free(folder->fl_subfolders_tab);
175 free_msgs_hash:
176#if 0
177 cinthash_free(folder->fl_msgs_hash);
178#endif
179 chash_free(folder->fl_msgs_hash);
180 free_msgs_tab:
181 carray_free(folder->fl_msgs_tab);
182 free_name:
183 free(folder->fl_name);
184 free_filename:
185 free(folder->fl_filename);
186 free_folder:
187 free(folder);
188 err:
189 return NULL;
190}
191
192void mailmh_folder_free(struct mailmh_folder * folder)
193{
194 unsigned int i;
195
196 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
197 struct mailmh_folder * subfolder;
198
199 subfolder = carray_get(folder->fl_subfolders_tab, i);
200 if (subfolder != NULL)
201 mailmh_folder_free(subfolder);
202 }
203 carray_free(folder->fl_subfolders_tab);
204 chash_free(folder->fl_subfolders_hash);
205
206 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
207 struct mailmh_msg_info * msg_info;
208
209 msg_info = carray_get(folder->fl_msgs_tab, i);
210 if (msg_info != NULL)
211 mailmh_msg_info_free(msg_info);
212 }
213 carray_free(folder->fl_msgs_tab);
214 chash_free(folder->fl_msgs_hash);
215#if 0
216 cinthash_free(folder->fl_msgs_hash);
217#endif
218
219 free(folder->fl_filename);
220 free(folder->fl_name);
221
222 free(folder);
223}
224
225struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root,
226 const char * filename)
227{
228 int r;
229 char pathname[PATH_MAX];
230 char * p;
231 chashdatum key;
232 chashdatum data;
233 struct mailmh_folder * folder;
234 char * start;
235
236 if (strcmp(root->fl_filename, filename) == 0)
237 return root;
238
239#if 0
240 r = mailmh_folder_update(root);
241 if (r != MAILMH_NO_ERROR)
242 return NULL;
243#endif
244
245#if 0
246 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) {
247 struct mailmh_folder * subfolder;
248
249 subfolder = carray_get(root->fl_subfolders_tab, i);
250 if (subfolder != NULL)
251 if (strncmp(subfolder->fl_filename, filename,
252 strlen(subfolder->fl_filename)) == 0)
253 return mailmh_folder_find(subfolder, filename);
254 }
255#endif
256 strncpy(pathname, filename, PATH_MAX);
257 pathname[PATH_MAX - 1] = 0;
258 start = pathname + strlen(root->fl_filename) + 1;
259
260 p = strchr(start, MAIL_DIR_SEPARATOR);
261 if (p != NULL) {
262 * p = 0;
263
264 root = mailmh_folder_find(root, pathname);
265 if (root != NULL) {
266 folder = mailmh_folder_find(root, filename);
267 if (folder == NULL)
268 return NULL;
269 return folder;
270 }
271
272 return NULL;
273 }
274 else {
275 key.data = pathname;
276 key.len = strlen(pathname);
277 r = chash_get(root->fl_subfolders_hash, &key, &data);
278 if (r < 0)
279 return NULL;
280
281 return data.data;
282 }
283}
284
285int mailmh_folder_update(struct mailmh_folder * folder)
286{
287 DIR * d;
288 struct dirent * ent;
289 struct stat buf;
290 char * mh_seq;
291 char filename[PATH_MAX];
292 int res;
293 int r;
294 uint32_t max_index;
295#if 0
296 int add_folder;
297#endif
298 unsigned int i;
299
300 if (stat(folder->fl_filename, &buf) == -1) {
301 res = MAILMH_ERROR_FOLDER;
302 goto err;
303 }
304
305 if (folder->fl_mtime == buf.st_mtime) {
306 res = MAILMH_NO_ERROR;
307 goto err;
308 }
309
310 folder->fl_mtime = buf.st_mtime;
311
312 d = opendir(folder->fl_filename);
313 if (d == NULL) {
314 res = MAILMH_ERROR_FOLDER;
315 goto err;
316 }
317
318 max_index = 0;
319
320#if 0
321 if (folder->fl_subfolders_tab->len == 0)
322 add_folder = 1;
323 else
324 add_folder = 0;
325#endif
326
327 /* clear the message list */
328
329 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
330 struct mailmh_msg_info * msg_info;
331 chashdatum key;
332
333 msg_info = carray_get(folder->fl_msgs_tab, i);
334 if (msg_info == NULL)
335 continue;
336
337#if 0
338 cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index);
339#endif
340 key.data = &msg_info->msg_index;
341 key.len = sizeof(msg_info->msg_index);
342 chash_delete(folder->fl_msgs_hash, &key, NULL);
343
344 mailmh_msg_info_free(msg_info);
345 }
346
347 carray_set_size(folder->fl_msgs_tab, 0);
348
349 do {
350 uint32_t index;
351
352 ent = readdir(d);
353
354 if (ent != NULL) {
355
356 snprintf(filename, PATH_MAX,
357 "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name);
358
359 if (stat(filename, &buf) == -1)
360 continue;
361
362 if (S_ISREG(buf.st_mode)) {
363 index = strtoul(ent->d_name, NULL, 10);
364 if (index != 0) {
365 struct mailmh_msg_info * msg_info;
366 unsigned int array_index;
367 chashdatum key;
368 chashdatum data;
369
370 msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime);
371 if (msg_info == NULL) {
372 res = MAILMH_ERROR_MEMORY;
373 goto closedir;
374 }
375
376 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
377 if (r < 0) {
378 mailmh_msg_info_free(msg_info);
379 res = MAILMH_ERROR_MEMORY;
380 goto closedir;
381 }
382 msg_info->msg_array_index = array_index;
383
384 if (index > max_index)
385 max_index = index;
386
387#if 0
388 r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info);
389#endif
390 key.data = &msg_info->msg_index;
391 key.len = sizeof(msg_info->msg_index);
392 data.data = msg_info;
393 data.len = 0;
394
395 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
396 if (r < 0) {
397 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
398 mailmh_msg_info_free(msg_info);
399 res = MAILMH_ERROR_MEMORY;
400 goto closedir;
401 }
402 }
403 }
404 else if (S_ISDIR(buf.st_mode)) {
405 struct mailmh_folder * subfolder;
406 unsigned int array_index;
407 chashdatum key;
408 chashdatum data;
409
410 if (ent->d_name[0] == '.') {
411 if (ent->d_name[1] == 0)
412 continue;
413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))
414 continue;
415 }
416
417 key.data = ent->d_name;
418 key.len = strlen(ent->d_name);
419 r = chash_get(folder->fl_subfolders_hash, &key, &data);
420 if (r < 0) {
421 subfolder = mailmh_folder_new(folder, ent->d_name);
422 if (subfolder == NULL) {
423 res = MAILMH_ERROR_MEMORY;
424 goto closedir;
425 }
426
427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index);
428 if (r < 0) {
429 mailmh_folder_free(subfolder);
430 res = MAILMH_ERROR_MEMORY;
431 goto closedir;
432 }
433 subfolder->fl_array_index = array_index;
434
435 key.data = subfolder->fl_filename;
436 key.len = strlen(subfolder->fl_filename);
437 data.data = subfolder;
438 data.len = 0;
439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL);
440 if (r < 0) {
441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index);
442 mailmh_folder_free(subfolder);
443 res = MAILMH_ERROR_MEMORY;
444 goto closedir;
445 }
446 }
447 }
448 }
449 }
450 while (ent != NULL);
451
452 folder->fl_max_index = max_index;
453
454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences"));
455 if (mh_seq == NULL) {
456 res = MAILMH_ERROR_MEMORY;
457 goto closedir;
458 }
459 strcpy(mh_seq, folder->fl_filename);
460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S);
461 strcat(mh_seq, ".mh_sequences");
462
463 if (stat(mh_seq, &buf) == -1) {
464 int fd;
465
466 fd = creat(mh_seq, S_IRUSR | S_IWUSR);
467 if (fd != -1)
468 close(fd);
469 }
470 free(mh_seq);
471
472 closedir(d);
473
474 return MAILMH_NO_ERROR;
475
476 closedir:
477 closedir(d);
478 err:
479 return res;
480}
481
482int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
483 const char * name)
484{
485 char * foldername;
486 int r;
487 struct mailmh_folder * folder;
488 unsigned int array_index;
489 chashdatum key;
490 chashdatum data;
491
492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2);
493 if (foldername == NULL)
494 return MAILMH_ERROR_MEMORY;
495 strcpy(foldername, parent->fl_filename);
496 strcat(foldername, MAIL_DIR_SEPARATOR_S);
497 strcat(foldername, name);
498
499 r = mkdir(foldername, 0700);
500 free(foldername);
501
502 if (r < 0)
503 return MAILMH_ERROR_FOLDER;
504
505 folder = mailmh_folder_new(parent, name);
506 if (folder == NULL)
507 return MAILMH_ERROR_MEMORY;
508
509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index);
510 if (r < 0) {
511 mailmh_folder_free(folder);
512 return MAILMH_ERROR_MEMORY;
513 }
514 folder->fl_array_index = array_index;
515
516 key.data = folder->fl_filename;
517 key.len = strlen(folder->fl_filename);
518 data.data = folder;
519 data.len = 0;
520
521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL);
522 if (r < 0) {
523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index);
524 mailmh_folder_free(folder);
525 return MAILMH_ERROR_MEMORY;
526 }
527
528 return MAILMH_NO_ERROR;
529}
530
531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder)
532{
533 struct mailmh_folder * parent;
534 chashdatum key;
535 chashdatum data;
536 int r;
537
538 parent = folder->fl_parent;
539
540 key.data = folder->fl_filename;
541 key.len = strlen(folder->fl_filename);
542
543 r = chash_get(parent->fl_subfolders_hash, &key, &data);
544 if (r < 0)
545 return MAILMH_ERROR_FOLDER;
546
547 chash_delete(parent->fl_subfolders_hash, &key, NULL);
548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index);
549
550 mailmh_folder_free(folder);
551
552 return MAILMH_NO_ERROR;
553
554}
555
556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
557 struct mailmh_folder * dst_folder,
558 const char * new_name)
559{
560 int r;
561 struct mailmh_folder * folder;
562 struct mailmh_folder * parent;
563 char * new_foldername;
564
565 parent = src_folder->fl_parent;
566 if (parent == NULL)
567 return MAILMH_ERROR_RENAME;
568
569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name));
570 if (new_foldername == NULL)
571 return MAILMH_ERROR_MEMORY;
572
573 strcpy(new_foldername, dst_folder->fl_filename);
574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S);
575 strcat(new_foldername, new_name);
576
577 r = rename(src_folder->fl_filename, new_foldername);
578 free(new_foldername);
579 if (r < 0)
580 return MAILMH_ERROR_RENAME;
581
582 r = mailmh_folder_remove_subfolder(src_folder);
583 if (r != MAILMH_NO_ERROR)
584 return r;
585
586 folder = mailmh_folder_new(dst_folder, new_name);
587 if (folder == NULL)
588 return MAILMH_ERROR_MEMORY;
589
590 r = carray_add(parent->fl_subfolders_tab, folder, NULL);
591 if (r < 0) {
592 mailmh_folder_free(folder);
593 return MAILMH_ERROR_MEMORY;
594 }
595
596 return MAILMH_NO_ERROR;
597}
598
599#define MAX_TRY_ALLOC 32
600
601/* initial file MUST be in the same directory */
602
603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder,
604 char * filename, uint32_t * result)
605{
606 uint32_t max;
607 uint32_t k;
608 char * new_filename;
609 size_t len;
610 int got_file;
611 int r;
612
613 len = strlen(folder->fl_filename) + 20;
614 new_filename = malloc(len);
615 if (new_filename == NULL)
616 return MAILMH_ERROR_MEMORY;
617
618 max = folder->fl_max_index + 1;
619
620 got_file = 0;
621 k = 0;
622 while (k < MAX_TRY_ALLOC) {
623 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename,
624 MAIL_DIR_SEPARATOR, (unsigned long) (max + k));
625
626 if (link(filename, new_filename) == 0) {
627 unlink(filename);
628 }
629 else if (errno == EXDEV) {
630 free(filename);
631 return MAILMH_ERROR_FOLDER;
632 }
633 else if (errno == EPERM) {
634 rename(filename, new_filename);
635 got_file = 1;
636 }
637
638 if (got_file) {
639 free(new_filename);
640
641 if (k > MAX_TRY_ALLOC / 2) {
642 r = mailmh_folder_update(folder);
643 /* ignore errors */
644 }
645
646 * result = max + k;
647
648 folder->fl_max_index = max + k;
649
650 return MAILMH_NO_ERROR;
651 }
652 k ++;
653 }
654
655 free(new_filename);
656
657 return MAILMH_ERROR_FOLDER;
658}
659
660int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
661 uint32_t index, char ** result)
662{
663 char * filename;
664 int len;
665
666#if 0
667 r = mailmh_folder_update(folder);
668 if (r != MAILMH_NO_ERROR)
669 return r;
670#endif
671
672 len = strlen(folder->fl_filename) + 20;
673 filename = malloc(len);
674 if (filename == NULL)
675 return MAILMH_ERROR_MEMORY;
676
677 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR,
678 (unsigned long) index);
679
680 * result = filename;
681
682 return MAILMH_NO_ERROR;;
683}
684
685
686int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
687 uint32_t index, int flags, int * result)
688{
689 char * filename;
690 int fd;
691 int r;
692
693#if 0
694 r = mailmh_folder_update(folder);
695 if (r != MAILMH_NO_ERROR)
696 return r;
697#endif
698
699 r = mailmh_folder_get_message_filename(folder, index, &filename);
700 if (r != MAILMH_NO_ERROR)
701 return r;
702
703 fd = open(filename, flags);
704 free(filename);
705 if (fd == -1)
706 return MAILMH_ERROR_MSG_NOT_FOUND;
707
708 * result = fd;
709
710 return MAILMH_NO_ERROR;
711}
712
713int mailmh_folder_get_message_size(struct mailmh_folder * folder,
714 uint32_t index, size_t * result)
715{
716 int r;
717 char * filename;
718 struct stat buf;
719
720 r = mailmh_folder_get_message_filename(folder, index, &filename);
721 if (r != MAILMH_NO_ERROR)
722 return r;
723
724 r = stat(filename, &buf);
725 free(filename);
726 if (r < 0)
727 return MAILMH_ERROR_FILE;
728
729 * result = buf.st_size;
730
731 return MAILMH_NO_ERROR;
732}
733
734int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
735 const char * message, size_t size,
736 uint32_t * pindex)
737{
738 char * tmpname;
739 int fd;
740 size_t namesize;
741 size_t left;
742 ssize_t res;
743 struct mailmh_msg_info * msg_info;
744 uint32_t index;
745 int error;
746 int r;
747 unsigned int array_index;
748 struct stat buf;
749 chashdatum key;
750 chashdatum data;
751
752#if 0
753 r = mailmh_folder_update(folder);
754 if (r != MAILMH_NO_ERROR) {
755 error = r;
756 goto err;
757 }
758#endif
759
760 namesize = strlen(folder->fl_filename) + 20;
761 tmpname = malloc(namesize);
762 snprintf(tmpname, namesize, "%s%ctmpXXXXXX",
763 folder->fl_filename, MAIL_DIR_SEPARATOR);
764 fd = mkstemp(tmpname);
765 if (fd < 0) {
766 error = MAILMH_ERROR_FILE;
767 goto free;
768 }
769
770 left = size;
771 while (left > 0) {
772 res = write(fd, message, left);
773 if (res == -1) {
774 close(fd);
775 error = MAILMH_ERROR_FILE;
776 goto free;
777 }
778
779 left -= res;
780 }
781 close(fd);
782
783 r = stat(tmpname, &buf);
784 if (r < 0) {
785 error = MAILMH_ERROR_FILE;
786 goto free;
787 }
788
789 r = mailmh_folder_alloc_msg(folder, tmpname, &index);
790 if (r != MAILMH_NO_ERROR) {
791 unlink(tmpname);
792 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG;
793 goto free;
794 }
795 free(tmpname);
796
797 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime);
798 if (msg_info == NULL) {
799 mailmh_folder_remove_message(folder, index);
800 error = MAILMH_ERROR_MEMORY;
801 goto err;
802 }
803
804 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
805 if (r < 0) {
806 mailmh_folder_remove_message(folder, index);
807 mailmh_msg_info_free(msg_info);
808 error = MAILMH_ERROR_MEMORY;
809 goto err;
810 }
811 msg_info->msg_array_index = array_index;
812
813#if 0
814 r = cinthash_add(folder->fl_msgs_hash, index, msg_info);
815#endif
816 key.data = &index;
817 key.len = sizeof(index);
818 data.data = msg_info;
819 data.len = 0;
820
821 if (pindex != NULL)
822 * pindex = index;
823
824 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
825 if (r < 0) {
826 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
827 mailmh_msg_info_free(msg_info);
828 error = MAILMH_ERROR_MEMORY;
829 goto err;
830 }
831
832 return MAILMH_NO_ERROR;
833
834 free:
835 free(tmpname);
836 err:
837 return error;
838}
839
840int mailmh_folder_add_message(struct mailmh_folder * folder,
841 const char * message, size_t size)
842{
843 return mailmh_folder_add_message_uid(folder, message, size, NULL);
844}
845
846int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
847 int fd, uint32_t * pindex)
848{
849 char * message;
850 struct stat buf;
851 int r;
852
853#if 0
854 r = mailmh_folder_update(folder);
855 if (r != MAILMH_NO_ERROR)
856 return r;
857#endif
858
859 if (fstat(fd, &buf) == -1)
860 return MAILMH_ERROR_FILE;
861
862 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
863 if (message == MAP_FAILED)
864 return MAILMH_ERROR_FILE;
865
866 r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex);
867
868 munmap(message, buf.st_size);
869
870 return r;
871}
872
873int mailmh_folder_add_message_file(struct mailmh_folder * folder,
874 int fd)
875{
876 return mailmh_folder_add_message_file_uid(folder, fd, NULL);
877}
878
879int mailmh_folder_remove_message(struct mailmh_folder * folder,
880 uint32_t index)
881{
882 char * filename;
883 struct mailmh_msg_info * msg_info;
884 int res;
885 int r;
886 chashdatum key;
887 chashdatum data;
888
889#if 0
890 r = mailmh_folder_update(folder);
891 if (r != MAILMH_NO_ERROR) {
892 res = r;
893 goto err;
894 }
895#endif
896
897 r = mailmh_folder_get_message_filename(folder, index, &filename);
898 if (filename == NULL) {
899 res = r;
900 goto err;
901 }
902
903 if (unlink(filename) == -1) {
904 res = MAILMH_ERROR_FILE;
905 goto free;
906 }
907
908 key.data = &index;
909 key.len = sizeof(index);
910 r = chash_get(folder->fl_msgs_hash, &key, &data);
911#if 0
912 msg_info = cinthash_find(folder->fl_msgs_hash, index);
913#endif
914 if (r == 0) {
915 msg_info = data.data;
916
917 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
918#if 0
919 cinthash_remove(folder->fl_msgs_hash, index);
920#endif
921 chash_delete(folder->fl_msgs_hash, &key, NULL);
922 }
923
924 return MAILMH_NO_ERROR;
925
926 free:
927 free(filename);
928 err:
929 return res;
930}
931
932
933int mailmh_folder_move_message(struct mailmh_folder * dest_folder,
934 struct mailmh_folder * src_folder,
935 uint32_t index)
936{
937 int fd;
938 char * filename;
939 int r;
940
941#if 0
942 r = mailmh_folder_update(dest_folder);
943 if (r != MAILMH_NO_ERROR)
944 return r;
945 r = mailmh_folder_update(src_folder);
946 if (r != MAILMH_NO_ERROR)
947 return r;
948#endif
949
950 /* move on the same filesystem */
951 r = mailmh_folder_get_message_filename(src_folder, index, &filename);
952 if (r != MAILMH_NO_ERROR)
953 return r;
954
955 r = mailmh_folder_alloc_msg(dest_folder, filename, &index);
956 free(filename);
957 if (r == MAILMH_NO_ERROR)
958 return MAILMH_NO_ERROR;
959
960 /* move on the different filesystems */
961 r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd);
962 if (r != MAILMH_NO_ERROR)
963 return r;
964
965 r = mailmh_folder_add_message_file(dest_folder, fd);
966 if (r != MAILMH_NO_ERROR) {
967 close(fd);
968 return r;
969 }
970
971 close(fd);
972
973 r = mailmh_folder_remove_message(src_folder, index);
974
975 return MAILMH_NO_ERROR;
976}
977
978unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder)
979{
980 unsigned int i;
981 unsigned int count;
982
983 count = 0;
984 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++)
985 if (carray_get(folder->fl_msgs_tab, i) != NULL)
986 count ++;
987
988 return count;
989}
diff --git a/libetpan/src/low-level/mh/mailmh.h b/libetpan/src/low-level/mh/mailmh.h
new file mode 100644
index 0000000..dc1861b
--- a/dev/null
+++ b/libetpan/src/low-level/mh/mailmh.h
@@ -0,0 +1,152 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMH_H
37
38#define MAILMH_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46#include <libetpan/carray.h>
47#if 0
48#include <libetpan/cinthash.h>
49#endif
50#include <libetpan/chash.h>
51
52enum {
53 MAILMH_NO_ERROR = 0,
54 MAILMH_ERROR_FOLDER,
55 MAILMH_ERROR_MEMORY,
56 MAILMH_ERROR_FILE,
57 MAILMH_ERROR_COULD_NOT_ALLOC_MSG,
58 MAILMH_ERROR_RENAME,
59 MAILMH_ERROR_MSG_NOT_FOUND,
60};
61
62struct mailmh {
63 struct mailmh_folder * mh_main;
64};
65
66struct mailmh_msg_info {
67 unsigned int msg_array_index;
68 uint32_t msg_index;
69 size_t msg_size;
70 time_t msg_mtime;
71};
72
73struct mailmh_folder {
74 char * fl_filename;
75 unsigned int fl_array_index;
76
77 char * fl_name;
78 time_t fl_mtime;
79 struct mailmh_folder * fl_parent;
80 uint32_t fl_max_index;
81
82 carray * fl_msgs_tab;
83#if 0
84 cinthash_t * fl_msgs_hash;
85#endif
86 chash * fl_msgs_hash;
87
88 carray * fl_subfolders_tab;
89 chash * fl_subfolders_hash;
90};
91
92struct mailmh * mailmh_new(const char * foldername);
93void mailmh_free(struct mailmh * f);
94
95struct mailmh_msg_info *
96mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime);
97void mailmh_msg_info_free(struct mailmh_msg_info * msg_info);
98
99struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent,
100 const char * name);
101void mailmh_folder_free(struct mailmh_folder * folder);
102
103int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
104 const char * name);
105
106struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root,
107 const char * filename);
108
109int mailmh_folder_remove_subfolder(struct mailmh_folder * folder);
110
111int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
112 struct mailmh_folder * dst_folder,
113 const char * new_name);
114
115int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
116 uint32_t index, char ** result);
117
118int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
119 uint32_t index, int flags, int * result);
120
121int mailmh_folder_get_message_size(struct mailmh_folder * folder,
122 uint32_t index, size_t * result);
123
124int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
125 const char * message, size_t size,
126 uint32_t * pindex);
127
128int mailmh_folder_add_message(struct mailmh_folder * folder,
129 const char * message, size_t size);
130
131int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
132 int fd, uint32_t * pindex);
133
134int mailmh_folder_add_message_file(struct mailmh_folder * folder,
135 int fd);
136
137int mailmh_folder_remove_message(struct mailmh_folder * folder,
138 uint32_t index);
139
140int mailmh_folder_move_message(struct mailmh_folder * dest_folder,
141 struct mailmh_folder * src_folder,
142 uint32_t index);
143
144int mailmh_folder_update(struct mailmh_folder * folder);
145
146unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder);
147
148#ifdef __cplusplus
149}
150#endif
151
152#endif
diff --git a/libetpan/src/low-level/mime/TODO b/libetpan/src/low-level/mime/TODO
new file mode 100644
index 0000000..df02810
--- a/dev/null
+++ b/libetpan/src/low-level/mime/TODO
@@ -0,0 +1,10 @@
1- see about the RFC2047, beginning in mailmime_decode.[ch]
2- content-langage
3- single mime_field
4- RFC 2048
5- RFC 2049
6- RFC 2231
7- RFC 2387
8- RFC 2424
9- RFC 2557
10
diff --git a/libetpan/src/low-level/mime/mailmime.c b/libetpan/src/low-level/mime/mailmime.c
new file mode 100644
index 0000000..4bade55
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime.c
@@ -0,0 +1,1408 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime.h"
37
38/*
39 RFC 2045
40 RFC 2046
41 RFC 2047
42 RFC 2048
43 RFC 2049
44 RFC 2231
45 RFC 2387
46 RFC 2424
47 RFC 2557
48
49 RFC 2183 Content-Disposition
50
51 RFC 1766 Language
52 */
53
54#include <ctype.h>
55#include <stdlib.h>
56#include <string.h>
57
58#include "mailmime_types.h"
59#include "mailmime_disposition.h"
60#include "mailimf.h"
61
62#ifndef TRUE
63#define TRUE 1
64#endif
65
66#ifndef FALSE
67#define FALSE 0
68#endif
69
70static int mailmime_attribute_parse(const char * message, size_t length,
71 size_t * index,
72 char ** result);
73static int
74mailmime_composite_type_parse(const char * message, size_t length,
75 size_t * index,
76 struct mailmime_composite_type ** result);
77
78static int is_text(char ch);
79
80static int
81mailmime_discrete_type_parse(const char * message, size_t length,
82 size_t * index,
83 struct mailmime_discrete_type ** result);
84
85static int mailmime_mechanism_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailmime_mechanism ** result);
88
89static int mailmime_subtype_parse(const char * message, size_t length,
90 size_t * index, char ** result);
91
92static int is_token(char ch);
93
94static int mailmime_token_parse(const char * message, size_t length,
95 size_t * index,
96 char ** token);
97
98static int is_tspecials(char ch);
99
100static int mailmime_type_parse(const char * message, size_t length,
101 size_t * index,
102 struct mailmime_type ** result);
103
104/*
105int mailmime_version_parse(const char * message, guint32 length,
106 guint32 * index,
107 guint32 * result);
108*/
109
110/*
111static gboolean mailmime_x_token_parse(gconst char * message, guint32 length,
112 guint32 * index,
113 gchar ** result);
114*/
115
116/* ********************************************************************** */
117
118/*
119x attribute := token
120 ; Matching of attributes
121 ; is ALWAYS case-insensitive.
122*/
123
124static int mailmime_attribute_parse(const char * message, size_t length,
125 size_t * index,
126 char ** result)
127{
128 return mailmime_token_parse(message, length, index, result);
129}
130
131/*
132x composite-type := "message" / "multipart" / extension-token
133*/
134
135static int
136mailmime_composite_type_parse(const char * message, size_t length,
137 size_t * index,
138 struct mailmime_composite_type ** result)
139{
140 char * extension_token;
141 int type;
142 struct mailmime_composite_type * ct;
143 size_t cur_token;
144 int r;
145 int res;
146
147 cur_token = * index;
148
149 extension_token = NULL;
150
151 type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */
152
153 r = mailimf_token_case_insensitive_parse(message, length,
154 &cur_token, "message");
155 if (r == MAILIMF_NO_ERROR)
156 type = MAILMIME_COMPOSITE_TYPE_MESSAGE;
157
158 if (r == MAILIMF_ERROR_PARSE) {
159 r = mailimf_token_case_insensitive_parse(message, length,
160 &cur_token, "multipart");
161 if (r == MAILIMF_NO_ERROR)
162 type = MAILMIME_COMPOSITE_TYPE_MULTIPART;
163 }
164
165 if (r != MAILIMF_NO_ERROR) {
166 res = r;
167 goto err;
168 }
169
170 ct = mailmime_composite_type_new(type, extension_token);
171 if (ct == NULL) {
172 res = MAILIMF_ERROR_MEMORY;
173 goto free_extension;
174 }
175
176 * result = ct;
177 * index = cur_token;
178
179 return MAILIMF_NO_ERROR;
180
181 free_extension:
182 if (extension_token != NULL)
183 mailmime_extension_token_free(extension_token);
184 err:
185 return res;
186}
187
188/*
189x content := "Content-Type" ":" type "/" subtype
190 *(";" parameter)
191 ; Matching of media type and subtype
192 ; is ALWAYS case-insensitive.
193*/
194
195int mailmime_content_parse(const char * message, size_t length,
196 size_t * index,
197 struct mailmime_content ** result)
198{
199 size_t cur_token;
200 struct mailmime_type * type;
201 char * subtype;
202 clist * parameters_list;
203 struct mailmime_content * content;
204 int r;
205 int res;
206
207 cur_token = * index;
208
209 mailimf_cfws_parse(message, length, &cur_token);
210
211 r = mailmime_type_parse(message, length, &cur_token, &type);
212 if (r != MAILIMF_NO_ERROR) {
213 res = r;
214 goto err;
215 }
216
217 r = mailimf_unstrict_char_parse(message, length, &cur_token, '/');
218 switch (r) {
219 case MAILIMF_NO_ERROR:
220 r = mailimf_cfws_parse(message, length, &cur_token);
221 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
222 res = r;
223 goto free_type;
224 }
225
226 r = mailmime_subtype_parse(message, length, &cur_token, &subtype);
227 if (r != MAILIMF_NO_ERROR) {
228 res = r;
229 goto free_type;
230 }
231 break;
232
233 case MAILIMF_ERROR_PARSE:
234 subtype = strdup("unknown");
235 break;
236
237 default:
238 res = r;
239 goto free_type;
240 }
241
242 parameters_list = clist_new();
243 if (parameters_list == NULL) {
244 res = MAILIMF_ERROR_MEMORY;
245 goto free_type;
246 }
247
248 while (1) {
249 size_t final_token;
250 struct mailmime_parameter * parameter;
251
252 final_token = cur_token;
253 r = mailimf_unstrict_char_parse(message, length, &cur_token, ';');
254 if (r != MAILIMF_NO_ERROR) {
255 cur_token = final_token;
256 break;
257 }
258
259 r = mailimf_cfws_parse(message, length, &cur_token);
260 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
261 res = r;
262 goto free_type;
263 }
264
265 r = mailmime_parameter_parse(message, length, &cur_token, &parameter);
266 if (r == MAILIMF_NO_ERROR) {
267 /* do nothing */
268 }
269 else if (r == MAILIMF_ERROR_PARSE) {
270 cur_token = final_token;
271 break;
272 }
273 else {
274 res = r;
275 goto err;
276 }
277
278 r = clist_append(parameters_list, parameter);
279 if (r < 0) {
280 mailmime_parameter_free(parameter);
281 res = MAILIMF_ERROR_MEMORY;
282 goto free_parameters;
283 }
284 }
285
286 content = mailmime_content_new(type, subtype, parameters_list);
287 if (content == NULL) {
288 res = MAILIMF_ERROR_MEMORY;
289 goto free_parameters;
290 }
291
292 * result = content;
293 * index = cur_token;
294
295 return MAILIMF_NO_ERROR;
296
297 free_parameters:
298 clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL);
299 clist_free(parameters_list);
300
301 mailmime_subtype_free(subtype);
302 free_type:
303 mailmime_type_free(type);
304 err:
305 return res;
306}
307
308/*
309x description := "Content-Description" ":" *text
310*/
311
312static int is_text(char ch)
313{
314 unsigned char uch = (unsigned char) ch;
315
316 if (uch < 1)
317 return FALSE;
318
319 if ((uch == 10) || (uch == 13))
320 return FALSE;
321
322 return TRUE;
323}
324
325int mailmime_description_parse(const char * message, size_t length,
326 size_t * index,
327 char ** result)
328{
329 return mailimf_custom_string_parse(message, length,
330 index, result,
331 is_text);
332}
333
334/*
335x discrete-type := "text" / "image" / "audio" / "video" /
336 "application" / extension-token
337*/
338
339/* currently porting */
340
341static int
342mailmime_discrete_type_parse(const char * message, size_t length,
343 size_t * index,
344 struct mailmime_discrete_type ** result)
345{
346 char * extension;
347 int type;
348 struct mailmime_discrete_type * discrete_type;
349 size_t cur_token;
350 int r;
351 int res;
352
353 cur_token = * index;
354
355 extension = NULL;
356
357 type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */
358
359 r = mailimf_token_case_insensitive_parse(message, length,
360 &cur_token, "text");
361 if (r == MAILIMF_NO_ERROR)
362 type = MAILMIME_DISCRETE_TYPE_TEXT;
363
364 if (r == MAILIMF_ERROR_PARSE) {
365 r = mailimf_token_case_insensitive_parse(message, length,
366 &cur_token, "image");
367 if (r == MAILIMF_NO_ERROR)
368 type = MAILMIME_DISCRETE_TYPE_IMAGE;
369 }
370
371 if (r == MAILIMF_ERROR_PARSE) {
372 r = mailimf_token_case_insensitive_parse(message, length,
373 &cur_token, "audio");
374 if (r == MAILIMF_NO_ERROR)
375 type = MAILMIME_DISCRETE_TYPE_AUDIO;
376 }
377
378 if (r == MAILIMF_ERROR_PARSE) {
379 r = mailimf_token_case_insensitive_parse(message, length,
380 &cur_token, "video");
381 if (r == MAILIMF_NO_ERROR)
382 type = MAILMIME_DISCRETE_TYPE_VIDEO;
383 }
384
385 if (r == MAILIMF_ERROR_PARSE) {
386 r = mailimf_token_case_insensitive_parse(message, length,
387 &cur_token, "application");
388 if (r == MAILIMF_NO_ERROR)
389 type = MAILMIME_DISCRETE_TYPE_APPLICATION;
390 }
391
392 if (r == MAILIMF_ERROR_PARSE) {
393 r = mailmime_extension_token_parse(message, length,
394 &cur_token, &extension);
395 if (r == MAILIMF_NO_ERROR)
396 type = MAILMIME_DISCRETE_TYPE_EXTENSION;
397 }
398
399 if (r != MAILIMF_NO_ERROR) {
400 res = r;
401 goto err;
402 }
403
404 discrete_type = mailmime_discrete_type_new(type, extension);
405 if (discrete_type == NULL) {
406 res = MAILIMF_ERROR_MEMORY;
407 goto free;
408 }
409
410 * result = discrete_type;
411 * index = cur_token;
412
413 return MAILIMF_NO_ERROR;
414
415 free:
416 mailmime_extension_token_free(extension);
417 err:
418 return res;
419}
420
421/*
422x encoding := "Content-Transfer-Encoding" ":" mechanism
423*/
424
425int mailmime_encoding_parse(const char * message, size_t length,
426 size_t * index,
427 struct mailmime_mechanism ** result)
428{
429 return mailmime_mechanism_parse(message, length, index, result);
430}
431
432/*
433x entity-headers := [ content CRLF ]
434 [ encoding CRLF ]
435 [ id CRLF ]
436 [ description CRLF ]
437 *( MIME-extension-field CRLF )
438 */
439
440enum {
441 FIELD_STATE_START,
442 FIELD_STATE_T,
443 FIELD_STATE_D
444};
445
446static int guess_field_type(char * name)
447{
448 int state;
449
450 if (* name == 'M')
451 return MAILMIME_FIELD_VERSION;
452
453 if (strncasecmp(name, "Content-", 8) != 0)
454 return MAILMIME_FIELD_NONE;
455
456 name += 8;
457
458 state = FIELD_STATE_START;
459
460 while (1) {
461
462 switch (state) {
463
464 case FIELD_STATE_START:
465 switch ((char) toupper((unsigned char) * name)) {
466 case 'T':
467 state = FIELD_STATE_T;
468 break;
469 case 'I':
470 return MAILMIME_FIELD_ID;
471 case 'D':
472 state = FIELD_STATE_D;
473 break;
474 case 'L':
475 return MAILMIME_FIELD_LANGUAGE;
476 default:
477 return MAILMIME_FIELD_NONE;
478 }
479 break;
480
481 case FIELD_STATE_T:
482 switch ((char) toupper((unsigned char) * name)) {
483 case 'Y':
484 return MAILMIME_FIELD_TYPE;
485 case 'R':
486 return MAILMIME_FIELD_TRANSFER_ENCODING;
487 default:
488 return MAILMIME_FIELD_NONE;
489 }
490 break;
491
492 case FIELD_STATE_D:
493 switch ((char) toupper((unsigned char) * name)) {
494 case 'E':
495 return MAILMIME_FIELD_DESCRIPTION;
496 case 'I':
497 return MAILMIME_FIELD_DISPOSITION;
498 default:
499 return MAILMIME_FIELD_NONE;
500 }
501 break;
502 }
503 name ++;
504 }
505}
506
507int
508mailmime_field_parse(struct mailimf_optional_field * field,
509 struct mailmime_field ** result)
510{
511 char * name;
512 char * value;
513 int guessed_type;
514 size_t cur_token;
515 struct mailmime_content * content;
516 struct mailmime_mechanism * encoding;
517 char * id;
518 char * description;
519 uint32_t version;
520 struct mailmime_field * mime_field;
521 struct mailmime_language * language;
522 struct mailmime_disposition * disposition;
523 int res;
524 int r;
525
526 name = field->fld_name;
527 value = field->fld_value;
528 cur_token = 0;
529
530 content = NULL;
531 encoding = NULL;
532 id = NULL;
533 description = NULL;
534 version = 0;
535 disposition = NULL;
536 language = NULL;
537
538 guessed_type = guess_field_type(name);
539
540 switch (guessed_type) {
541 case MAILMIME_FIELD_TYPE:
542 if (strcasecmp(name, "Content-Type") != 0)
543 return MAILIMF_ERROR_PARSE;
544 r = mailmime_content_parse(value, strlen(value), &cur_token, &content);
545 if (r != MAILIMF_NO_ERROR)
546 return r;
547 break;
548
549 case MAILMIME_FIELD_TRANSFER_ENCODING:
550 if (strcasecmp(name, "Content-Transfer-Encoding") != 0)
551 return MAILIMF_ERROR_PARSE;
552 r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding);
553 if (r != MAILIMF_NO_ERROR)
554 return r;
555 break;
556
557 case MAILMIME_FIELD_ID:
558 if (strcasecmp(name, "Content-ID") != 0)
559 return MAILIMF_ERROR_PARSE;
560 r = mailmime_id_parse(value, strlen(value), &cur_token, &id);
561 if (r != MAILIMF_NO_ERROR)
562 return r;
563 break;
564
565 case MAILMIME_FIELD_DESCRIPTION:
566 if (strcasecmp(name, "Content-Description") != 0)
567 return MAILIMF_ERROR_PARSE;
568 r = mailmime_description_parse(value, strlen(value),
569 &cur_token, &description);
570 if (r != MAILIMF_NO_ERROR)
571 return r;
572 break;
573
574 case MAILMIME_FIELD_VERSION:
575 if (strcasecmp(name, "MIME-Version") != 0)
576 return MAILIMF_ERROR_PARSE;
577 r = mailmime_version_parse(value, strlen(value), &cur_token, &version);
578 if (r != MAILIMF_NO_ERROR)
579 return r;
580 break;
581
582 case MAILMIME_FIELD_DISPOSITION:
583 if (strcasecmp(name, "Content-Disposition") != 0)
584 return MAILIMF_ERROR_PARSE;
585 r = mailmime_disposition_parse(value, strlen(value),
586 &cur_token, &disposition);
587 if (r != MAILIMF_NO_ERROR)
588 return r;
589 break;
590
591 case MAILMIME_FIELD_LANGUAGE:
592 if (strcasecmp(name, "Content-Language") != 0)
593 return MAILIMF_ERROR_PARSE;
594 r = mailmime_language_parse(value, strlen(value), &cur_token, &language);
595 if (r != MAILIMF_NO_ERROR)
596 return r;
597 break;
598
599 default:
600 return MAILIMF_ERROR_PARSE;
601 }
602
603 mime_field = mailmime_field_new(guessed_type, content, encoding,
604 id, description, version, disposition,
605 language);
606 if (mime_field == NULL) {
607 res = MAILIMF_ERROR_MEMORY;
608 goto free;
609 }
610
611 * result = mime_field;
612
613 return MAILIMF_NO_ERROR;
614
615 free:
616 if (content != NULL)
617 mailmime_content_free(content);
618 if (encoding != NULL)
619 mailmime_encoding_free(encoding);
620 if (id != NULL)
621 mailmime_id_free(id);
622 if (description != NULL)
623 mailmime_description_free(description);
624 return res;
625}
626
627/*
628x extension-token := ietf-token / x-token
629*/
630
631int
632mailmime_extension_token_parse(const char * message, size_t length,
633 size_t * index, char ** result)
634{
635 return mailmime_token_parse(message, length, index, result);
636}
637
638/*
639 hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
640 ; Octet must be used for characters > 127, =,
641 ; SPACEs or TABs at the ends of lines, and is
642 ; recommended for any character not listed in
643 ; RFC 2049 as "mail-safe".
644*/
645
646/*
647x iana-token := <A publicly-defined extension token. Tokens
648 of this form must be registered with IANA
649 as specified in RFC 2048.>
650*/
651
652/*
653x ietf-token := <An extension token defined by a
654 standards-track RFC and registered
655 with IANA.>
656*/
657
658/*
659x id := "Content-ID" ":" msg-id
660*/
661
662int mailmime_id_parse(const char * message, size_t length,
663 size_t * index, char ** result)
664{
665 return mailimf_msg_id_parse(message, length, index, result);
666}
667
668/*
669x mechanism := "7bit" / "8bit" / "binary" /
670 "quoted-printable" / "base64" /
671 ietf-token / x-token
672*/
673
674static int mailmime_mechanism_parse(const char * message, size_t length,
675 size_t * index,
676 struct mailmime_mechanism ** result)
677{
678 char * token;
679 int type;
680 struct mailmime_mechanism * mechanism;
681 size_t cur_token;
682 int r;
683 int res;
684
685 cur_token = * index;
686
687 type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */
688
689 token = NULL;
690 r = mailimf_token_case_insensitive_parse(message, length,
691 &cur_token, "7bit");
692 if (r == MAILIMF_NO_ERROR)
693 type = MAILMIME_MECHANISM_7BIT;
694
695 if (r == MAILIMF_ERROR_PARSE) {
696 r = mailimf_token_case_insensitive_parse(message, length,
697 &cur_token, "8bit");
698 if (r == MAILIMF_NO_ERROR)
699 type = MAILMIME_MECHANISM_8BIT;
700 }
701
702 if (r == MAILIMF_ERROR_PARSE) {
703 r = mailimf_token_case_insensitive_parse(message, length,
704 &cur_token, "binary");
705 if (r == MAILIMF_NO_ERROR)
706 type = MAILMIME_MECHANISM_BINARY;
707 }
708
709 if (r == MAILIMF_ERROR_PARSE) {
710 r = mailimf_token_case_insensitive_parse(message, length,
711 &cur_token, "quoted-printable");
712 if (r == MAILIMF_NO_ERROR)
713 type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
714 }
715
716 if (r == MAILIMF_ERROR_PARSE) {
717 r = mailimf_token_case_insensitive_parse(message, length,
718 &cur_token, "base64");
719 if (r == MAILIMF_NO_ERROR)
720 type = MAILMIME_MECHANISM_BASE64;
721 }
722
723 if (r == MAILIMF_ERROR_PARSE) {
724 r = mailmime_token_parse(message, length, &cur_token, &token);
725 if (r == MAILIMF_NO_ERROR)
726 type = MAILMIME_MECHANISM_TOKEN;
727 }
728
729 if (r != MAILIMF_NO_ERROR) {
730 res = r;
731 goto err;
732 }
733
734 mechanism = mailmime_mechanism_new(type, token);
735 if (mechanism == NULL) {
736 res = MAILIMF_ERROR_MEMORY;
737 goto free;
738 }
739
740 * result = mechanism;
741 * index = cur_token;
742
743 return MAILIMF_NO_ERROR;
744
745 free:
746 if (token != NULL)
747 mailmime_token_free(token);
748 err:
749 return res;
750}
751
752/*
753x MIME-extension-field := <Any RFC 822 header field which
754 begins with the string
755 "Content-">
756*/
757
758/*
759in headers
760
761x MIME-message-headers := entity-headers
762 fields
763 version CRLF
764 ; The ordering of the header
765 ; fields implied by this BNF
766 ; definition should be ignored.
767*/
768
769/*
770in message
771
772x MIME-part-headers := entity-headers
773 [fields]
774 ; Any field not beginning with
775 ; "content-" can have no defined
776 ; meaning and may be ignored.
777 ; The ordering of the header
778 ; fields implied by this BNF
779 ; definition should be ignored.
780*/
781
782#if 0
783int
784mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields *
785 fields,
786 struct mailmime_fields **
787 result)
788{
789 clistiter * cur;
790 struct mailmime_fields * mime_fields;
791 clist * list;
792 int r;
793 int res;
794
795 list = clist_new();
796 if (list == NULL) {
797 res = MAILIMF_ERROR_MEMORY;
798 goto err;
799 }
800
801 if (fields->list == NULL) {
802 res = MAILIMF_ERROR_PARSE;
803 goto err;
804 }
805
806 for(cur = clist_begin(fields->list) ; cur != NULL ;
807 cur = clist_next(cur)) {
808 struct mailimf_optional_field * field = cur->data;
809 struct mailmime_field * mime_field;
810
811 r = mailmime_field_parse(field, &mime_field);
812 if (r == MAILIMF_NO_ERROR) {
813 r = clist_append(list, mime_field);
814 if (r < 0) {
815 mailmime_field_free(mime_field);
816 res = MAILIMF_ERROR_MEMORY;
817 goto free_list;
818 }
819 }
820 }
821
822 if (clist_begin(list) == NULL) {
823 res = MAILIMF_ERROR_PARSE;
824 goto free_list;
825 }
826
827 mime_fields = mailmime_fields_new(list);
828 if (mime_fields == NULL) {
829 res = MAILIMF_ERROR_MEMORY;
830 goto free_list;
831 }
832
833 * result = mime_fields;
834
835 return MAILIMF_NO_ERROR;
836
837 free_list:
838 clist_foreach(list, (clist_func) mailmime_field_free, NULL);
839 clist_free(list);
840 err:
841 return res;
842}
843#endif
844
845int
846mailmime_fields_parse(struct mailimf_fields *
847 fields,
848 struct mailmime_fields **
849 result)
850{
851 clistiter * cur;
852 struct mailmime_fields * mime_fields;
853 clist * list;
854 int r;
855 int res;
856
857 list = clist_new();
858 if (list == NULL) {
859 res = MAILIMF_ERROR_MEMORY;
860 goto err;
861 }
862
863 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
864 cur = clist_next(cur)) {
865 struct mailimf_field * field;
866 struct mailmime_field * mime_field;
867
868 field = clist_content(cur);
869
870 if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) {
871 r = mailmime_field_parse(field->fld_data.fld_optional_field,
872 &mime_field);
873 if (r == MAILIMF_NO_ERROR) {
874 r = clist_append(list, mime_field);
875 if (r < 0) {
876 mailmime_field_free(mime_field);
877 res = MAILIMF_ERROR_MEMORY;
878 goto free_list;
879 }
880 }
881 else if (r == MAILIMF_ERROR_PARSE) {
882 /* do nothing */
883 }
884 else {
885 res = r;
886 goto free_list;
887 }
888 }
889 }
890
891 if (clist_begin(list) == NULL) {
892 res = MAILIMF_ERROR_PARSE;
893 goto free_list;
894 }
895
896 mime_fields = mailmime_fields_new(list);
897 if (mime_fields == NULL) {
898 res = MAILIMF_ERROR_MEMORY;
899 goto free_list;
900 }
901
902 * result = mime_fields;
903
904 return MAILIMF_NO_ERROR;
905
906 free_list:
907 clist_foreach(list, (clist_func) mailmime_field_free, NULL);
908 clist_free(list);
909 err:
910 return res;
911}
912
913/*
914x parameter := attribute "=" value
915*/
916
917int mailmime_parameter_parse(const char * message, size_t length,
918 size_t * index,
919 struct mailmime_parameter ** result)
920{
921 char * attribute;
922 char * value;
923 struct mailmime_parameter * parameter;
924 size_t cur_token;
925 int r;
926 int res;
927
928 cur_token = * index;
929
930 r = mailmime_attribute_parse(message, length, &cur_token, &attribute);
931 if (r != MAILIMF_NO_ERROR) {
932 res = r;
933 goto err;
934 }
935
936 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
937 if (r != MAILIMF_NO_ERROR) {
938 res = r;
939 goto free_attr;
940 }
941
942 r = mailimf_cfws_parse(message, length, &cur_token);
943 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
944 res = r;
945 goto free_attr;
946 }
947
948 r = mailmime_value_parse(message, length, &cur_token, &value);
949 if (r != MAILIMF_NO_ERROR) {
950 res = r;
951 goto free_attr;
952 }
953
954 parameter = mailmime_parameter_new(attribute, value);
955 if (parameter == NULL) {
956 res = MAILIMF_ERROR_MEMORY;
957 goto free_value;
958 }
959
960 * result = parameter;
961 * index = cur_token;
962
963 return MAILIMF_NO_ERROR;
964
965 free_value:
966 mailmime_value_free(value);
967 free_attr:
968 mailmime_attribute_free(attribute);
969 err:
970 return res;
971}
972
973/*
974 ptext := hex-octet / safe-char
975*/
976
977/*
978 qp-line := *(qp-segment transport-padding CRLF)
979 qp-part transport-padding
980*/
981
982/*
983 qp-part := qp-section
984 ; Maximum length of 76 characters
985*/
986
987/*
988 qp-section := [*(ptext / SPACE / TAB) ptext]
989*/
990
991/*
992 qp-segment := qp-section *(SPACE / TAB) "="
993 ; Maximum length of 76 characters
994*/
995
996/*
997 quoted-printable := qp-line *(CRLF qp-line)
998*/
999
1000/*
1001 safe-char := <any octet with decimal value of 33 through
1002 60 inclusive, and 62 through 126>
1003 ; Characters not listed as "mail-safe" in
1004 ; RFC 2049 are also not recommended.
1005*/
1006
1007/*
1008x subtype := extension-token / iana-token
1009*/
1010
1011static int mailmime_subtype_parse(const char * message, size_t length,
1012 size_t * index, char ** result)
1013{
1014 return mailmime_extension_token_parse(message, length, index, result);
1015}
1016
1017/*
1018x token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
1019 or tspecials>
1020*/
1021
1022static int is_token(char ch)
1023{
1024 unsigned char uch = (unsigned char) ch;
1025
1026 if (uch > 0x7F)
1027 return FALSE;
1028
1029 if (uch == ' ')
1030 return FALSE;
1031
1032 if (is_tspecials(ch))
1033 return FALSE;
1034
1035 return TRUE;
1036}
1037
1038
1039static int mailmime_token_parse(const char * message, size_t length,
1040 size_t * index,
1041 char ** token)
1042{
1043 return mailimf_custom_string_parse(message, length,
1044 index, token,
1045 is_token);
1046}
1047
1048/*
1049 transport-padding := *LWSP-char
1050 ; Composers MUST NOT generate
1051 ; non-zero length transport
1052 ; padding, but receivers MUST
1053 ; be able to handle padding
1054 ; added by message transports.
1055*/
1056
1057/*
1058enum {
1059 LWSP_1,
1060 LWSP_2,
1061 LWSP_3,
1062 LWSP_4,
1063 LWSP_OK
1064};
1065
1066gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length,
1067 guint32 * index)
1068{
1069 guint32 cur_token;
1070 gint state;
1071 guint32 last_valid_pos;
1072
1073 cur_token = * index;
1074
1075 if (cur_token >= length)
1076 return FALSE;
1077
1078 state = LWSP_1;
1079
1080 while (state != LWSP_OUT) {
1081
1082 if (cur_token >= length)
1083 return FALSE;
1084
1085 switch (state) {
1086 case LWSP_1:
1087 last_valid_pos = cur_token;
1088
1089 switch (message[cur_token]) {
1090 case '\r':
1091 state = LWSP_2;
1092 break;
1093 case '\n':
1094 state = LWSP_3;
1095 break;
1096 case ' ':
1097 case '\t':
1098 state = LWSP_4;
1099 break;
1100 default:
1101 state = LWSP_OK;
1102 break;
1103 }
1104 case LWSP_2:
1105 switch (message[cur_token]) {
1106 case '\n':
1107 state = LWSP_3;
1108 break;
1109 default:
1110 state = LWSP_OUT;
1111 cur_token = last_valid_pos;
1112 break;
1113 }
1114 case LWSP_3:
1115 switch (message[cur_token]) {
1116 case ' ':
1117 case '\t':
1118 state = LWSP_1;
1119 break;
1120 default:
1121 state = LWSP_OUT;
1122 cur_token = last_valid_pos;
1123 break;
1124 }
1125
1126 cur_token ++;
1127 }
1128 }
1129
1130 * index = cur_token;
1131
1132 return TRUE;
1133}
1134*/
1135
1136/*
1137x tspecials := "(" / ")" / "<" / ">" / "@" /
1138 "," / ";" / ":" / "\" / <">
1139 "/" / "[" / "]" / "?" / "="
1140 ; Must be in quoted-string,
1141 ; to use within parameter values
1142*/
1143
1144static int is_tspecials(char ch)
1145{
1146 switch (ch) {
1147 case '(':
1148 case ')':
1149 case '<':
1150 case '>':
1151 case '@':
1152 case ',':
1153 case ';':
1154 case ':':
1155 case '\\':
1156 case '\"':
1157 case '/':
1158 case '[':
1159 case ']':
1160 case '?':
1161 case '=':
1162 return TRUE;
1163 default:
1164 return FALSE;
1165 }
1166}
1167
1168/*
1169x type := discrete-type / composite-type
1170*/
1171
1172static int mailmime_type_parse(const char * message, size_t length,
1173 size_t * index,
1174 struct mailmime_type ** result)
1175{
1176 struct mailmime_discrete_type * discrete_type;
1177 struct mailmime_composite_type * composite_type;
1178 size_t cur_token;
1179 struct mailmime_type * mime_type;
1180 int type;
1181 int res;
1182 int r;
1183
1184 cur_token = * index;
1185
1186 discrete_type = NULL;
1187 composite_type = NULL;
1188
1189 type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */
1190
1191 r = mailmime_composite_type_parse(message, length, &cur_token,
1192 &composite_type);
1193 if (r == MAILIMF_NO_ERROR)
1194 type = MAILMIME_TYPE_COMPOSITE_TYPE;
1195
1196 if (r == MAILIMF_ERROR_PARSE) {
1197 r = mailmime_discrete_type_parse(message, length, &cur_token,
1198 &discrete_type);
1199 if (r == MAILIMF_NO_ERROR)
1200 type = MAILMIME_TYPE_DISCRETE_TYPE;
1201 }
1202
1203 if (r != MAILIMF_NO_ERROR) {
1204 res = r;
1205 goto err;
1206 }
1207
1208 mime_type = mailmime_type_new(type, discrete_type, composite_type);
1209 if (mime_type == NULL) {
1210 res = r;
1211 goto free;
1212 }
1213
1214 * result = mime_type;
1215 * index = cur_token;
1216
1217 return MAILIMF_NO_ERROR;
1218
1219 free:
1220 if (discrete_type != NULL)
1221 mailmime_discrete_type_free(discrete_type);
1222 if (composite_type != NULL)
1223 mailmime_composite_type_free(composite_type);
1224 err:
1225 return res;
1226}
1227
1228/*
1229x value := token / quoted-string
1230*/
1231
1232int mailmime_value_parse(const char * message, size_t length,
1233 size_t * index, char ** result)
1234{
1235 int r;
1236
1237 r = mailmime_token_parse(message, length, index, result);
1238
1239 if (r == MAILIMF_ERROR_PARSE)
1240 r = mailimf_quoted_string_parse(message, length, index, result);
1241
1242 if (r != MAILIMF_NO_ERROR)
1243 return r;
1244
1245 return MAILIMF_NO_ERROR;
1246}
1247
1248/*
1249x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
1250*/
1251
1252int mailmime_version_parse(const char * message, size_t length,
1253 size_t * index,
1254 uint32_t * result)
1255{
1256 size_t cur_token;
1257 uint32_t hi;
1258 uint32_t low;
1259 uint32_t version;
1260 int r;
1261
1262 cur_token = * index;
1263
1264 r = mailimf_number_parse(message, length, &cur_token, &hi);
1265 if (r != MAILIMF_NO_ERROR)
1266 return r;
1267
1268 r = mailimf_unstrict_char_parse(message, length, &cur_token, '.');
1269 if (r != MAILIMF_NO_ERROR)
1270 return r;
1271
1272 r = mailimf_cfws_parse(message, length, &cur_token);
1273 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
1274 return r;
1275
1276 r = mailimf_number_parse(message, length, &cur_token, &low);
1277 if (r != MAILIMF_NO_ERROR)
1278 return r;
1279
1280 version = (hi << 16) + low;
1281
1282 * result = version;
1283 * index = cur_token;
1284
1285 return MAILIMF_NO_ERROR;
1286}
1287
1288/*
1289x x-token := <The two characters "X-" or "x-" followed, with
1290 no intervening white space, by any token>
1291*/
1292
1293/*
1294static gboolean mailmime_x_token_parse(gconst char * message, guint32 length,
1295 guint32 * index,
1296 gchar ** result)
1297{
1298 guint32 cur_token;
1299 gchar * token;
1300 gchar * x_token;
1301 gboolean min_x;
1302
1303 cur_token = * index;
1304
1305 if (!mailimf_char_parse(message, length, &cur_token, 'x')) {
1306 if (!mailimf_char_parse(message, length, &cur_token, 'X'))
1307 return FALSE;
1308 min_x = FALSE;
1309 }
1310 else
1311 min_x = TRUE;
1312
1313 if (!mailimf_char_parse(message, length, &cur_token, '-'))
1314 return FALSE;
1315
1316 if (!mailmime_token_parse(message, length, &cur_token, &token))
1317 return FALSE;
1318
1319 if (min_x)
1320 x_token = g_strconcat("x-", token, NULL);
1321 else
1322 x_token = g_strconcat("X-", token, NULL);
1323 mailmime_token_free(token);
1324
1325 if (x_token == NULL)
1326 return FALSE;
1327
1328 * result = x_token;
1329 * index = cur_token;
1330
1331 return TRUE;
1332}
1333*/
1334
1335
1336int mailmime_language_parse(const char * message, size_t length,
1337 size_t * index,
1338 struct mailmime_language ** result)
1339{
1340 size_t cur_token;
1341 int r;
1342 int res;
1343 clist * list;
1344 int first;
1345 struct mailmime_language * language;
1346
1347 cur_token = * index;
1348
1349 list = clist_new();
1350 if (list == NULL) {
1351 res = MAILIMF_ERROR_MEMORY;
1352 goto err;
1353 }
1354
1355 first = TRUE;
1356
1357 while (1) {
1358 char * atom;
1359
1360 r = mailimf_unstrict_char_parse(message, length, &cur_token, ',');
1361 if (r == MAILIMF_NO_ERROR) {
1362 /* do nothing */
1363 }
1364 else if (r == MAILIMF_ERROR_PARSE) {
1365 break;
1366 }
1367 else {
1368 res = r;
1369 goto err;
1370 }
1371
1372 r = mailimf_atom_parse(message, length, &cur_token, &atom);
1373 if (r == MAILIMF_NO_ERROR) {
1374 /* do nothing */
1375 }
1376 else if (r == MAILIMF_ERROR_PARSE) {
1377 break;
1378 }
1379 else {
1380 res = r;
1381 goto err;
1382 }
1383
1384 r = clist_append(list, atom);
1385 if (r < 0) {
1386 mailimf_atom_free(atom);
1387 res = MAILIMF_ERROR_MEMORY;
1388 goto free;
1389 }
1390 }
1391
1392 language = mailmime_language_new(list);
1393 if (language == NULL) {
1394 res = MAILIMF_ERROR_MEMORY;
1395 goto free;
1396 }
1397
1398 * result = language;
1399 * index = cur_token;
1400
1401 return MAILIMF_NO_ERROR;
1402
1403 free:
1404 clist_foreach(list, (clist_func) mailimf_atom_free, NULL);
1405 clist_free(list);
1406 err:
1407 return res;
1408}
diff --git a/libetpan/src/low-level/mime/mailmime.h b/libetpan/src/low-level/mime/mailmime.h
new file mode 100644
index 0000000..83cba25
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_H
37
38#define MAILMIME_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailimf.h>
45#include <libetpan/mailmime_types.h>
46#include <libetpan/mailmime_types_helper.h>
47#include <libetpan/mailmime_content.h>
48#include <libetpan/mailmime_decode.h>
49#include <libetpan/mailmime_disposition.h>
50#include <libetpan/mailmime_write_file.h>
51#include <libetpan/mailmime_write_mem.h>
52#include <libetpan/mailmime_write_generic.h>
53
54int mailmime_content_parse(const char * message, size_t length,
55 size_t * index,
56 struct mailmime_content ** result);
57
58int mailmime_description_parse(const char * message, size_t length,
59 size_t * index,
60 char ** result);
61
62int mailmime_encoding_parse(const char * message, size_t length,
63 size_t * index,
64 struct mailmime_mechanism ** result);
65
66int
67mailmime_field_parse(struct mailimf_optional_field * field,
68 struct mailmime_field ** result);
69
70int mailmime_id_parse(const char * message, size_t length,
71 size_t * index, char ** result);
72
73int
74mailmime_fields_parse(struct mailimf_fields *
75 fields,
76 struct mailmime_fields **
77 result);
78
79int mailmime_version_parse(const char * message, size_t length,
80 size_t * index,
81 uint32_t * result);
82
83int
84mailmime_extension_token_parse(const char * message, size_t length,
85 size_t * index, char ** result);
86
87int mailmime_parameter_parse(const char * message, size_t length,
88 size_t * index,
89 struct mailmime_parameter ** result);
90
91int mailmime_value_parse(const char * message, size_t length,
92 size_t * index, char ** result);
93
94int mailmime_language_parse(const char * message, size_t length,
95 size_t * index,
96 struct mailmime_language ** result);
97
98#ifdef __cplusplus
99}
100#endif
101
102#endif
diff --git a/libetpan/src/low-level/mime/mailmime_content.c b/libetpan/src/low-level/mime/mailmime_content.c
new file mode 100644
index 0000000..6a10dfb
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_content.c
@@ -0,0 +1,2381 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailimf.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mailmime.h"
42#include "mailmime_types.h"
43#include "mmapstring.h"
44
45#ifndef TRUE
46#define TRUE 1
47#endif
48
49#ifndef FALSE
50#define FALSE 0
51#endif
52
53/*
54 RFC 2045
55 RFC 2046
56 RFC 2047
57
58 RFC 2231
59*/
60
61
62static int mailmime_parse_with_default(const char * message, size_t length,
63 size_t * index, int default_type,
64 struct mailmime_content * content_type,
65 struct mailmime_fields * mime_fields,
66 struct mailmime ** result);
67
68
69
70char * mailmime_content_charset_get(struct mailmime_content * content)
71{
72 char * charset;
73
74 charset = mailmime_content_param_get(content, "charset");
75 if (charset == NULL)
76 return "us-ascii";
77 else
78 return charset;
79}
80
81char * mailmime_content_param_get(struct mailmime_content * content,
82 char * name)
83{
84 clistiter * cur;
85
86 for(cur = clist_begin(content->ct_parameters) ;
87 cur != NULL ; cur = clist_next(cur)) {
88 struct mailmime_parameter * param;
89
90 param = clist_content(cur);
91
92 if (strcasecmp(param->pa_name, name) == 0)
93 return param->pa_value;
94 }
95
96 return NULL;
97}
98
99
100/*
101 boundary := 0*69<bchars> bcharsnospace
102*/
103
104/*
105 bchars := bcharsnospace / " "
106*/
107
108/*
109 bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" /
110 "+" / "_" / "," / "-" / "." /
111 "/" / ":" / "=" / "?"
112*/
113
114/*
115 body-part := <"message" as defined in RFC 822, with all
116 header fields optional, not starting with the
117 specified dash-boundary, and with the
118 delimiter not occurring anywhere in the
119 body part. Note that the semantics of a
120 part differ from the semantics of a message,
121 as described in the text.>
122*/
123
124/*
125 close-delimiter := delimiter "--"
126*/
127
128/*
129 dash-boundary := "--" boundary
130 ; boundary taken from the value of
131 ; boundary parameter of the
132 ; Content-Type field.
133*/
134
135/*
136 delimiter := CRLF dash-boundary
137*/
138
139/*
140 discard-text := *(*text CRLF)
141 ; May be ignored or discarded.
142*/
143
144/*
145 encapsulation := delimiter transport-padding
146 CRLF body-part
147*/
148
149/*
150 epilogue := discard-text
151*/
152
153/*
154 multipart-body := [preamble CRLF]
155 dash-boundary transport-padding CRLF
156 body-part *encapsulation
157 close-delimiter transport-padding
158 [CRLF epilogue]
159*/
160
161/*
162 preamble := discard-text
163*/
164
165/*
166 transport-padding := *LWSP-char
167 ; Composers MUST NOT generate
168 ; non-zero length transport
169 ; padding, but receivers MUST
170 ; be able to handle padding
171 ; added by message transports.
172*/
173
174
175/*
176 ACCESS-TYPE
177 EXPIRATION
178 SIZE
179 PERMISSION
180*/
181
182/*
183 5.2.3.2. The 'ftp' and 'tftp' Access-Types
184 NAME
185 SITE
186
187 (3) Before any data are retrieved, using FTP, the user will
188 generally need to be asked to provide a login id and a
189 password for the machine named by the site parameter.
190 For security reasons, such an id and password are not
191 specified as content-type parameters, but must be
192 obtained from the user.
193
194 optional :
195 DIRECTORY
196 MODE
197*/
198
199/*
2005.2.3.3. The 'anon-ftp' Access-Type
201*/
202
203/*
2045.2.3.4. The 'local-file' Access-Type
205NAME
206SITE
207*/
208
209/*
2105.2.3.5. The 'mail-server' Access-Type
211SERVER
212SUBJECT
213*/
214
215
216enum {
217 PREAMBLE_STATE_A0,
218 PREAMBLE_STATE_A,
219 PREAMBLE_STATE_A1,
220 PREAMBLE_STATE_B,
221 PREAMBLE_STATE_C,
222 PREAMBLE_STATE_D,
223 PREAMBLE_STATE_E
224};
225
226static int mailmime_preamble_parse(const char * message, size_t length,
227 size_t * index, int beol)
228{
229 int state;
230 size_t cur_token;
231
232 cur_token = * index;
233 if (beol)
234 state = PREAMBLE_STATE_A0;
235 else
236 state = PREAMBLE_STATE_A;
237
238 while (state != PREAMBLE_STATE_E) {
239
240 if (cur_token >= length)
241 return MAILIMF_ERROR_PARSE;
242
243 switch (state) {
244 case PREAMBLE_STATE_A0:
245 switch (message[cur_token]) {
246 case '-':
247 state = PREAMBLE_STATE_A1;
248 break;
249 case '\r':
250 state = PREAMBLE_STATE_B;
251 break;
252 case '\n':
253 state = PREAMBLE_STATE_C;
254 break;
255 default:
256 state = PREAMBLE_STATE_A;
257 break;
258 }
259 break;
260
261 case PREAMBLE_STATE_A:
262 switch (message[cur_token]) {
263 case '\r':
264 state = PREAMBLE_STATE_B;
265 break;
266 case '\n':
267 state = PREAMBLE_STATE_C;
268 break;
269 default:
270 state = PREAMBLE_STATE_A;
271 break;
272 }
273 break;
274
275 case PREAMBLE_STATE_A1:
276 switch (message[cur_token]) {
277 case '-':
278 state = PREAMBLE_STATE_E;
279 break;
280 case '\r':
281 state = PREAMBLE_STATE_B;
282 break;
283 case '\n':
284 state = PREAMBLE_STATE_C;
285 break;
286 default:
287 state = PREAMBLE_STATE_A;
288 break;
289 }
290 break;
291
292 case PREAMBLE_STATE_B:
293 switch (message[cur_token]) {
294 case '\r':
295 state = PREAMBLE_STATE_B;
296 break;
297 case '\n':
298 state = PREAMBLE_STATE_C;
299 break;
300 case '-':
301 state = PREAMBLE_STATE_D;
302 break;
303 default:
304 state = PREAMBLE_STATE_A0;
305 break;
306 }
307 break;
308
309 case PREAMBLE_STATE_C:
310 switch (message[cur_token]) {
311 case '-':
312 state = PREAMBLE_STATE_D;
313 break;
314 case '\r':
315 state = PREAMBLE_STATE_B;
316 break;
317 case '\n':
318 state = PREAMBLE_STATE_C;
319 break;
320 default:
321 state = PREAMBLE_STATE_A0;
322 break;
323 }
324 break;
325
326 case PREAMBLE_STATE_D:
327 switch (message[cur_token]) {
328 case '-':
329 state = PREAMBLE_STATE_E;
330 break;
331 default:
332 state = PREAMBLE_STATE_A;
333 break;
334 }
335 break;
336 }
337
338 cur_token ++;
339 }
340
341 * index = cur_token;
342
343 return MAILIMF_NO_ERROR;
344}
345
346static int mailmime_boundary_parse(const char * message, size_t length,
347 size_t * index, char * boundary)
348{
349 size_t cur_token;
350 size_t len;
351
352 cur_token = * index;
353
354 len = strlen(boundary);
355
356 if (cur_token + len >= length)
357 return MAILIMF_ERROR_PARSE;
358
359 if (strncmp(message + cur_token, boundary, len) != 0)
360 return MAILIMF_ERROR_PARSE;
361
362 cur_token += len;
363
364 * index = cur_token;
365
366 return MAILIMF_NO_ERROR;
367}
368
369static int is_wsp(char ch)
370{
371 if ((ch == ' ') || (ch == '\t'))
372 return TRUE;
373
374 return FALSE;
375}
376
377static int mailmime_lwsp_parse(const char * message, size_t length,
378 size_t * index)
379{
380 size_t cur_token;
381
382 cur_token = * index;
383
384 if (cur_token >= length)
385 return MAILIMF_ERROR_PARSE;
386
387 while (is_wsp(message[cur_token])) {
388 cur_token ++;
389 if (cur_token >= length)
390 break;
391 }
392
393 if (cur_token == * index)
394 return MAILIMF_ERROR_PARSE;
395
396 * index = cur_token;
397
398 return MAILIMF_NO_ERROR;
399}
400
401/*
402gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index)
403*/
404
405enum {
406 BODY_PART_DASH2_STATE_0,
407 BODY_PART_DASH2_STATE_1,
408 BODY_PART_DASH2_STATE_2,
409 BODY_PART_DASH2_STATE_3,
410 BODY_PART_DASH2_STATE_4,
411 BODY_PART_DASH2_STATE_5,
412 BODY_PART_DASH2_STATE_6
413};
414
415static int
416mailmime_body_part_dash2_parse(const char * message, size_t length,
417 size_t * index, char * boundary,
418 const char ** result, size_t * result_size)
419{
420 int state;
421 size_t cur_token;
422 size_t size;
423 size_t begin_text;
424 size_t end_text;
425 int r;
426
427 cur_token = * index;
428 state = BODY_PART_DASH2_STATE_0;
429
430 begin_text = cur_token;
431 end_text = length;
432
433 while (state != BODY_PART_DASH2_STATE_5) {
434
435 if (cur_token >= length)
436 break;
437
438 switch(state) {
439
440 case BODY_PART_DASH2_STATE_0:
441 switch (message[cur_token]) {
442 case '\r':
443 state = BODY_PART_DASH2_STATE_1;
444 break;
445 case '\n':
446 state = BODY_PART_DASH2_STATE_2;
447 break;
448 default:
449 state = BODY_PART_DASH2_STATE_0;
450 break;
451 }
452 break;
453
454 case BODY_PART_DASH2_STATE_1:
455 switch (message[cur_token]) {
456 case '\n':
457 state = BODY_PART_DASH2_STATE_2;
458 break;
459 default:
460 state = BODY_PART_DASH2_STATE_0;
461 break;
462 }
463 break;
464
465 case BODY_PART_DASH2_STATE_2:
466 switch (message[cur_token]) {
467 case '-':
468 end_text = cur_token;
469 state = BODY_PART_DASH2_STATE_3;
470 break;
471 case '\r':
472 state = BODY_PART_DASH2_STATE_1;
473 break;
474 case '\n':
475 state = BODY_PART_DASH2_STATE_2;
476 break;
477 default:
478 state = BODY_PART_DASH2_STATE_0;
479 break;
480 }
481 break;
482
483 case BODY_PART_DASH2_STATE_3:
484 switch (message[cur_token]) {
485 case '\r':
486 state = BODY_PART_DASH2_STATE_1;
487 break;
488 case '\n':
489 state = BODY_PART_DASH2_STATE_2;
490 break;
491 case '-':
492 state = BODY_PART_DASH2_STATE_4;
493 break;
494 default:
495 state = BODY_PART_DASH2_STATE_0;
496 break;
497 }
498 break;
499
500 case BODY_PART_DASH2_STATE_4:
501 r = mailmime_boundary_parse(message, length, &cur_token, boundary);
502 if (r == MAILIMF_NO_ERROR)
503 state = BODY_PART_DASH2_STATE_5;
504 else
505 state = BODY_PART_DASH2_STATE_6;
506
507 break;
508 }
509
510 if ((state != BODY_PART_DASH2_STATE_5) &&
511 (state != BODY_PART_DASH2_STATE_6))
512 cur_token ++;
513
514 if (state == BODY_PART_DASH2_STATE_6)
515 state = BODY_PART_DASH2_STATE_0;
516 }
517
518 size = end_text - begin_text;
519
520#if 0
521 if (size > 0) {
522 end_text --;
523 size --;
524 }
525#endif
526
527 if (size >= 1) {
528 if (message[end_text - 1] == '\r') {
529 end_text --;
530 size --;
531 }
532 else if (size >= 1) {
533 if (message[end_text - 1] == '\n') {
534 end_text --;
535 size --;
536 if (size >= 1) {
537 if (message[end_text - 1] == '\r') {
538 end_text --;
539 size --;
540 }
541 }
542 }
543 }
544 }
545
546 size = end_text - begin_text;
547 if (size == 0)
548 return MAILIMF_ERROR_PARSE;
549
550#if 0
551 body_part = mailimf_body_new(message + begin_text, size);
552 if (body_part == NULL)
553 goto err;
554#endif
555
556 * result = message + begin_text;
557 * result_size = size;
558 * index = cur_token;
559
560 return MAILIMF_NO_ERROR;
561#if 0
562 err:
563 return MAILIMF_ERROR_PARSE;
564#endif
565}
566
567static int
568mailmime_body_part_dash2_transport_crlf_parse(const char * message,
569 size_t length,
570 size_t * index, char * boundary,
571 const char ** result, size_t * result_size)
572{
573 size_t cur_token;
574 int r;
575 size_t after_boundary;
576 const char * data_str;
577 size_t data_size;
578 const char * begin_text;
579 const char * end_text;
580
581 cur_token = * index;
582
583 begin_text = message + cur_token;
584 end_text = message + cur_token;
585
586 while (1) {
587 r = mailmime_body_part_dash2_parse(message, length, &cur_token,
588 boundary, &data_str, &data_size);
589 if (r == MAILIMF_NO_ERROR) {
590 end_text = data_str + data_size;
591 }
592 else {
593 return r;
594 }
595
596 /* parse transport-padding */
597 while (1) {
598 r = mailmime_lwsp_parse(message, length, &cur_token);
599 if (r == MAILIMF_NO_ERROR) {
600 /* do nothing */
601 }
602 else if (r == MAILIMF_ERROR_PARSE) {
603 break;
604 }
605 else {
606 return r;
607 }
608 }
609
610 r = mailimf_crlf_parse(message, length, &cur_token);
611 if (r == MAILIMF_NO_ERROR) {
612 break;
613 }
614 else if (r == MAILIMF_ERROR_PARSE) {
615 /* do nothing */
616 }
617 else {
618 return r;
619 }
620 }
621
622 * index = cur_token;
623 * result = begin_text;
624 * result_size = end_text - begin_text;
625
626 return MAILIMF_NO_ERROR;
627}
628
629static int mailmime_multipart_close_parse(const char * message, size_t length,
630 size_t * index);
631
632static int
633mailmime_body_part_dash2_close_parse(const char * message,
634 size_t length,
635 size_t * index, char * boundary,
636 const char ** result, size_t * result_size)
637{
638 size_t cur_token;
639 int r;
640 size_t after_boundary;
641 const char * data_str;
642 size_t data_size;
643 const char * begin_text;
644 const char * end_text;
645
646 cur_token = * index;
647
648 begin_text = message + cur_token;
649 end_text = message + cur_token;
650
651 while (1) {
652 r = mailmime_body_part_dash2_parse(message, length,
653 &cur_token, boundary, &data_str, &data_size);
654 if (r == MAILIMF_NO_ERROR) {
655 end_text = data_str + data_size;
656 }
657 else {
658 return r;
659 }
660
661 r = mailmime_multipart_close_parse(message, length, &cur_token);
662 if (r == MAILIMF_NO_ERROR) {
663 break;
664 }
665 else if (r == MAILIMF_ERROR_PARSE) {
666 /* do nothing */
667 }
668 else {
669 return r;
670 }
671 }
672
673 * index = cur_token;
674 * result = data_str;
675 * result_size = data_size;
676
677 return MAILIMF_NO_ERROR;
678}
679
680enum {
681 MULTIPART_CLOSE_STATE_0,
682 MULTIPART_CLOSE_STATE_1,
683 MULTIPART_CLOSE_STATE_2,
684 MULTIPART_CLOSE_STATE_3,
685 MULTIPART_CLOSE_STATE_4
686};
687
688static int mailmime_multipart_close_parse(const char * message, size_t length,
689 size_t * index)
690{
691 int state;
692 size_t cur_token;
693
694 cur_token = * index;
695 state = MULTIPART_CLOSE_STATE_0;
696
697 while (state != MULTIPART_CLOSE_STATE_4) {
698
699 switch(state) {
700
701 case MULTIPART_CLOSE_STATE_0:
702 if (cur_token >= length)
703 return MAILIMF_ERROR_PARSE;
704
705 switch (message[cur_token]) {
706 case '-':
707 state = MULTIPART_CLOSE_STATE_1;
708 break;
709 default:
710 return MAILIMF_ERROR_PARSE;
711 }
712 break;
713
714 case MULTIPART_CLOSE_STATE_1:
715 if (cur_token >= length)
716 return MAILIMF_ERROR_PARSE;
717
718 switch (message[cur_token]) {
719 case '-':
720 state = MULTIPART_CLOSE_STATE_2;
721 break;
722 default:
723 return MAILIMF_ERROR_PARSE;
724 }
725 break;
726
727 case MULTIPART_CLOSE_STATE_2:
728 if (cur_token >= length) {
729 state = MULTIPART_CLOSE_STATE_4;
730 break;
731 }
732
733 switch (message[cur_token]) {
734 case ' ':
735 state = MULTIPART_CLOSE_STATE_2;
736 break;
737 case '\t':
738 state = MULTIPART_CLOSE_STATE_2;
739 break;
740 case '\r':
741 state = MULTIPART_CLOSE_STATE_3;
742 break;
743 case '\n':
744 state = MULTIPART_CLOSE_STATE_4;
745 break;
746 default:
747 state = MULTIPART_CLOSE_STATE_4;
748 break;
749 }
750 break;
751
752 case MULTIPART_CLOSE_STATE_3:
753 if (cur_token >= length) {
754 state = MULTIPART_CLOSE_STATE_4;
755 break;
756 }
757
758 switch (message[cur_token]) {
759 case '\n':
760 state = MULTIPART_CLOSE_STATE_4;
761 break;
762 default:
763 state = MULTIPART_CLOSE_STATE_4;
764 break;
765 }
766 break;
767 }
768
769 cur_token ++;
770 }
771
772 * index = cur_token;
773
774 return MAILIMF_NO_ERROR;
775}
776
777enum {
778 MULTIPART_NEXT_STATE_0,
779 MULTIPART_NEXT_STATE_1,
780 MULTIPART_NEXT_STATE_2
781};
782
783int mailmime_multipart_next_parse(const char * message, size_t length,
784 size_t * index)
785{
786 int state;
787 size_t cur_token;
788
789 cur_token = * index;
790 state = MULTIPART_NEXT_STATE_0;
791
792 while (state != MULTIPART_NEXT_STATE_2) {
793
794 if (cur_token >= length)
795 return MAILIMF_ERROR_PARSE;
796
797 switch(state) {
798
799 case MULTIPART_NEXT_STATE_0:
800 switch (message[cur_token]) {
801 case ' ':
802 state = MULTIPART_NEXT_STATE_0;
803 break;
804 case '\t':
805 state = MULTIPART_NEXT_STATE_0;
806 break;
807 case '\r':
808 state = MULTIPART_NEXT_STATE_1;
809 break;
810 case '\n':
811 state = MULTIPART_NEXT_STATE_2;
812 break;
813 default:
814 return MAILIMF_ERROR_PARSE;
815 }
816 break;
817
818 case MULTIPART_NEXT_STATE_1:
819 switch (message[cur_token]) {
820 case '\n':
821 state = MULTIPART_NEXT_STATE_2;
822 break;
823 default:
824 return MAILIMF_ERROR_PARSE;
825 }
826 break;
827 }
828
829 cur_token ++;
830 }
831
832 * index = cur_token;
833
834 return MAILIMF_NO_ERROR;
835}
836
837static int
838mailmime_multipart_body_parse(const char * message, size_t length,
839 size_t * index, char * boundary,
840 int default_subtype,
841 clist ** result,
842 struct mailmime_data ** p_preamble,
843 struct mailmime_data ** p_epilogue)
844{
845 size_t cur_token;
846 clist * list;
847 int r;
848 int res;
849#if 0
850 size_t begin;
851#endif
852 size_t preamble_begin;
853 size_t preamble_length;
854 size_t preamble_end;
855#if 0
856 int no_preamble;
857 size_t before_crlf;
858#endif
859 size_t epilogue_begin;
860 size_t epilogue_length;
861 struct mailmime_data * preamble;
862 struct mailmime_data * epilogue;
863 size_t part_begin;
864 int final_part;
865
866 preamble = NULL;
867 epilogue = NULL;
868
869 cur_token = * index;
870 preamble_begin = cur_token;
871
872#if 0
873 no_preamble = FALSE;
874#endif
875 preamble_end = preamble_begin;
876
877#if 0
878 r = mailmime_preamble_parse(message, length, &cur_token);
879 if (r == MAILIMF_NO_ERROR) {
880 /* do nothing */
881#if 0
882 preamble_end = cur_token - 2;
883#endif
884 }
885 else if (r == MAILIMF_ERROR_PARSE) {
886 /* do nothing */
887 no_preamble = TRUE;
888 }
889 else {
890 res = r;
891 goto err;
892 }
893
894 while (1) {
895
896 preamble_end = cur_token;
897 r = mailmime_boundary_parse(message, length, &cur_token, boundary);
898 if (r == MAILIMF_NO_ERROR) {
899 break;
900 }
901 else if (r == MAILIMF_ERROR_PARSE) {
902 /* do nothing */
903 }
904 else {
905 res = r;
906 goto err;
907 }
908
909 r = mailmime_preamble_parse(message, length, &cur_token);
910 if (r == MAILIMF_NO_ERROR) {
911#if 0
912 preamble_end = cur_token - 2;
913#endif
914 }
915 else if (r == MAILIMF_ERROR_PARSE) {
916 no_preamble = TRUE;
917 break;
918 }
919 else {
920 res = r;
921 goto err;
922 }
923 }
924
925 if (no_preamble) {
926#if 0
927 preamble_end = cur_token;
928#endif
929 }
930 else {
931
932 r = mailmime_lwsp_parse(message, length, &cur_token);
933 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
934 res = r;
935 goto err;
936 }
937
938 before_crlf = cur_token;
939 r = mailimf_crlf_parse(message, length, &cur_token);
940 if (r == MAILIMF_NO_ERROR) {
941#if 0
942 preamble_end = before_crlf;
943#endif
944 /* remove the CR LF at the end of preamble if any */
945 }
946 else if (r == MAILIMF_ERROR_PARSE) {
947 /* do nothing */
948 }
949 else {
950 res = r;
951 goto err;
952 }
953 }
954 preamble_length = preamble_end - begin;
955#endif
956
957 r = mailmime_preamble_parse(message, length, &cur_token, 1);
958 if (r == MAILIMF_NO_ERROR) {
959 while (1) {
960
961 preamble_end = cur_token;
962 r = mailmime_boundary_parse(message, length, &cur_token, boundary);
963 if (r == MAILIMF_NO_ERROR) {
964 break;
965 }
966 else if (r == MAILIMF_ERROR_PARSE) {
967 /* do nothing */
968 }
969 else {
970 res = r;
971 goto err;
972 }
973
974 r = mailmime_preamble_parse(message, length, &cur_token, 0);
975 if (r == MAILIMF_NO_ERROR) {
976 }
977 else if (r == MAILIMF_ERROR_PARSE) {
978 break;
979 }
980 else {
981 res = r;
982 goto err;
983 }
984 }
985 }
986
987 preamble_end -= 2;
988 if (preamble_end != preamble_begin) {
989 /* try to find the real end of the preamble (strip CR LF) */
990 if (message[preamble_end - 1] == '\n') {
991 preamble_end --;
992 if (preamble_end - 1 >= preamble_begin) {
993 if (message[preamble_end - 1] == '\r')
994 preamble_end --;
995 }
996 }
997 else if (message[preamble_end - 1] == '\r') {
998 preamble_end --;
999 }
1000 }
1001 preamble_length = preamble_end - preamble_begin;
1002
1003 part_begin = cur_token;
1004 while (1) {
1005 r = mailmime_lwsp_parse(message, length, &cur_token);
1006 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1007 res = r;
1008 goto err;
1009 }
1010#if 0
1011 if (r == MAILIMF_ERROR_PARSE)
1012 break;
1013#endif
1014
1015 r = mailimf_crlf_parse(message, length, &cur_token);
1016 if (r == MAILIMF_NO_ERROR) {
1017 part_begin = cur_token;
1018 }
1019 else if (r == MAILIMF_ERROR_PARSE) {
1020 /* do nothing */
1021 break;
1022 }
1023 else {
1024 res = r;
1025 goto err;
1026 }
1027 }
1028
1029 cur_token = part_begin;
1030
1031 list = clist_new();
1032 if (list == NULL) {
1033 res = MAILIMF_ERROR_MEMORY;
1034 goto err;
1035 }
1036
1037 final_part = 0;
1038
1039 while (!final_part) {
1040 size_t bp_token;
1041 struct mailmime * mime_bp;
1042 const char * data_str;
1043 size_t data_size;
1044 struct mailimf_fields * fields;
1045 struct mailmime_fields * mime_fields;
1046 int got_crlf;
1047 size_t after_boundary;
1048
1049#if 0
1050 /* XXX - begin */
1051 r = mailmime_body_part_dash2_parse(message, length, &cur_token,
1052 boundary, &data_str, &data_size);
1053 if (r == MAILIMF_NO_ERROR) {
1054 /* do nothing */
1055 }
1056 else if (r == MAILIMF_ERROR_PARSE) {
1057 break;
1058 }
1059 else {
1060 res = r;
1061 goto free;
1062 }
1063
1064 after_boundary = cur_token;
1065 got_crlf = 0;
1066 /* parse transport-padding */
1067 while (1) {
1068 r = mailmime_lwsp_parse(message, length, &cur_token);
1069 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1070 res = r;
1071 goto free;
1072 }
1073
1074 r = mailimf_crlf_parse(message, length, &cur_token);
1075 if (r == MAILIMF_NO_ERROR) {
1076 got_crlf = 1;
1077 break;
1078 }
1079 else if (r == MAILIMF_ERROR_PARSE) {
1080 /* do nothing */
1081 break;
1082 }
1083 else {
1084 res = r;
1085 goto free;
1086 }
1087 }
1088 if (after_boundary != cur_token) {
1089 if (!got_crlf) {
1090 r = mailimf_crlf_parse(message, length, &cur_token);
1091 if (r == MAILIMF_NO_ERROR) {
1092 got_crlf = 1;
1093 break;
1094 }
1095 }
1096 }
1097 /* XXX - end */
1098#endif
1099
1100 r = mailmime_body_part_dash2_transport_crlf_parse(message, length,
1101 &cur_token, boundary, &data_str, &data_size);
1102 if (r == MAILIMF_ERROR_PARSE) {
1103 r = mailmime_body_part_dash2_close_parse(message, length,
1104 &cur_token, boundary, &data_str, &data_size);
1105 if (r == MAILIMF_NO_ERROR) {
1106 final_part = 1;
1107 }
1108 }
1109
1110 if (r == MAILIMF_NO_ERROR) {
1111 bp_token = 0;
1112
1113 r = mailimf_optional_fields_parse(data_str, data_size,
1114 &bp_token, &fields);
1115 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1116 res = r;
1117 goto free;
1118 }
1119
1120 r = mailimf_crlf_parse(data_str, data_size, &bp_token);
1121 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1122 mailimf_fields_free(fields);
1123 res = r;
1124 goto free;
1125 }
1126
1127 mime_fields = NULL;
1128 r = mailmime_fields_parse(fields, &mime_fields);
1129 mailimf_fields_free(fields);
1130 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1131 res = r;
1132 goto free;
1133 }
1134
1135 r = mailmime_parse_with_default(data_str, data_size,
1136 &bp_token, default_subtype, NULL,
1137 mime_fields, &mime_bp);
1138 if (r == MAILIMF_NO_ERROR) {
1139 r = clist_append(list, mime_bp);
1140 if (r < 0) {
1141 mailmime_free(mime_bp);
1142 res = MAILIMF_ERROR_MEMORY;
1143 goto free;
1144 }
1145 }
1146 else if (r == MAILIMF_ERROR_PARSE) {
1147 mailmime_fields_free(mime_fields);
1148 break;
1149 }
1150 else {
1151 mailmime_fields_free(mime_fields);
1152 res = r;
1153 goto free;
1154 }
1155
1156 r = mailmime_multipart_next_parse(message, length, &cur_token);
1157 if (r == MAILIMF_NO_ERROR) {
1158 /* do nothing */
1159 }
1160 }
1161 else {
1162 res = r;
1163 goto free;
1164 }
1165
1166#if 0
1167 else if (r == MAILIMF_ERROR_PARSE) {
1168 r = mailmime_body_part_dash2_parse(message, length,
1169 &cur_token, boundary, &data_str, &data_size);
1170 if (r != MAILIMF_NO_ERROR) {
1171 res = r;
1172 goto free;
1173 }
1174
1175 r = mailmime_multipart_close_parse(message, length, &cur_token);
1176 if (r == MAILIMF_NO_ERROR) {
1177 break;
1178 }
1179 else if (r == MAILIMF_ERROR_PARSE) {
1180 res = r;
1181 goto free;
1182#if 0
1183 fprintf(stderr, "close not found, reparse %s\n", boundary);
1184 /* reparse */
1185 continue;
1186#endif
1187 }
1188 else {
1189 res = r;
1190 goto free;
1191 }
1192 }
1193 else {
1194 res = r;
1195 goto free;
1196 }
1197#endif
1198 }
1199
1200 epilogue_begin = length;
1201 /* parse transport-padding */
1202 while (1) {
1203 r = mailmime_lwsp_parse(message, length, &cur_token);
1204 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1205 res = r;
1206 goto free;
1207 }
1208
1209 if (r == MAILIMF_ERROR_PARSE)
1210 break;
1211
1212#if 0
1213 if (r == MAILIMF_ERROR_PARSE)
1214 break;
1215#endif
1216
1217#if 0
1218 before_crlf = cur_token;
1219#endif
1220 }
1221
1222 r = mailimf_crlf_parse(message, length, &cur_token);
1223 if (r == MAILIMF_NO_ERROR) {
1224 epilogue_begin = cur_token;
1225 }
1226 else if (r != MAILIMF_ERROR_PARSE) {
1227 res = r;
1228 goto free;
1229 }
1230
1231 /* add preamble and epilogue */
1232
1233 epilogue_length = length - epilogue_begin;
1234
1235 if (preamble_length != 0) {
1236 preamble = mailmime_data_new(MAILMIME_DATA_TEXT,
1237 MAILMIME_MECHANISM_8BIT, 1,
1238 message + preamble_begin, preamble_length,
1239 NULL);
1240 if (preamble == NULL) {
1241 res = MAILIMF_ERROR_MEMORY;
1242 goto free;
1243 }
1244 }
1245
1246 if (epilogue_length != 0) {
1247 epilogue = mailmime_data_new(MAILMIME_DATA_TEXT,
1248 MAILMIME_MECHANISM_8BIT, 1,
1249 message + epilogue_begin, epilogue_length,
1250 NULL);
1251 if (epilogue == NULL) {
1252 res = MAILIMF_ERROR_MEMORY;
1253 goto free;
1254 }
1255 }
1256
1257 /* end of preamble and epilogue */
1258
1259 cur_token = length;
1260
1261 * result = list;
1262 * p_preamble = preamble;
1263 * p_epilogue = epilogue;
1264 * index = cur_token;
1265
1266 return MAILIMF_NO_ERROR;
1267
1268 free:
1269 if (epilogue != NULL)
1270 mailmime_data_free(epilogue);
1271 if (preamble != NULL)
1272 mailmime_data_free(preamble);
1273 clist_foreach(list, (clist_func) mailmime_free, NULL);
1274 clist_free(list);
1275 err:
1276 return res;
1277}
1278
1279enum {
1280 MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1281 MAILMIME_DEFAULT_TYPE_MESSAGE
1282};
1283
1284
1285int mailmime_parse(const char * message, size_t length,
1286 size_t * index, struct mailmime ** result)
1287{
1288 struct mailmime * mime;
1289 int r;
1290 int res;
1291 struct mailmime_content * content_message;
1292 size_t cur_token;
1293 struct mailmime_fields * mime_fields;
1294 const char * data_str;
1295 size_t data_size;
1296 size_t bp_token;
1297
1298 cur_token = * index;
1299
1300 content_message = mailmime_get_content_message();
1301 if (content_message == NULL) {
1302 res = MAILIMF_ERROR_MEMORY;
1303 goto err;
1304 }
1305
1306#if 0
1307 mime_fields = mailmime_fields_new_with_data(content_message,
1308 NULL,
1309 NULL,
1310 NULL,
1311 NULL,
1312 NULL);
1313 if (mime_fields == NULL) {
1314 mailmime_content_free(content_message);
1315 res = MAILIMF_ERROR_MEMORY;
1316 goto err;
1317 }
1318#endif
1319 mime_fields = mailmime_fields_new_empty();
1320 if (mime_fields == NULL) {
1321 mailmime_content_free(content_message);
1322 res = MAILIMF_ERROR_MEMORY;
1323 goto err;
1324 }
1325
1326 data_str = message + cur_token;
1327 data_size = length - cur_token;
1328
1329 bp_token = 0;
1330 r = mailmime_parse_with_default(data_str, data_size,
1331 &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1332 content_message, mime_fields, &mime);
1333 cur_token += bp_token;
1334 if (r != MAILIMF_NO_ERROR) {
1335 mailmime_fields_free(mime_fields);
1336 res = r;
1337 goto free;
1338 }
1339
1340 * index = cur_token;
1341 * result = mime;
1342
1343 return MAILIMF_NO_ERROR;
1344
1345 free:
1346 mailmime_fields_free(mime_fields);
1347 err:
1348 return res;
1349}
1350
1351
1352char * mailmime_extract_boundary(struct mailmime_content * content_type)
1353{
1354 char * boundary;
1355
1356 boundary = mailmime_content_param_get(content_type, "boundary");
1357
1358 if (boundary != NULL) {
1359 int len;
1360 char * new_boundary;
1361
1362 len = strlen(boundary);
1363 new_boundary = malloc(len + 1);
1364 if (new_boundary == NULL)
1365 return NULL;
1366
1367 if (boundary[0] == '"') {
1368 strncpy(new_boundary, boundary + 1, len - 2);
1369 new_boundary[len - 2] = 0;
1370 }
1371 else
1372 strcpy(new_boundary, boundary);
1373
1374 boundary = new_boundary;
1375 }
1376
1377 return boundary;
1378}
1379
1380static void remove_unparsed_mime_headers(struct mailimf_fields * fields)
1381{
1382 clistiter * cur;
1383
1384 cur = clist_begin(fields->fld_list);
1385 while (cur != NULL) {
1386 struct mailimf_field * field;
1387 int delete;
1388
1389 field = clist_content(cur);
1390
1391 switch (field->fld_type) {
1392 case MAILIMF_FIELD_OPTIONAL_FIELD:
1393 delete = 0;
1394 if (strncasecmp(field->fld_data.fld_optional_field->fld_name,
1395 "Content-", 8) == 0) {
1396 char * name;
1397
1398 name = field->fld_data.fld_optional_field->fld_name + 8;
1399 if ((strcasecmp(name, "Type") == 0)
1400 || (strcasecmp(name, "Transfer-Encoding") == 0)
1401 || (strcasecmp(name, "ID") == 0)
1402 || (strcasecmp(name, "Description") == 0)
1403 || (strcasecmp(name, "Disposition") == 0)
1404 || (strcasecmp(name, "Language") == 0)) {
1405 delete = 1;
1406 }
1407 }
1408 else if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
1409 "MIME-Version") == 0) {
1410 delete = 1;
1411 }
1412
1413 if (delete) {
1414 cur = clist_delete(fields->fld_list, cur);
1415 mailimf_field_free(field);
1416 }
1417 else {
1418 cur = clist_next(cur);
1419 }
1420 break;
1421
1422 default:
1423 cur = clist_next(cur);
1424 }
1425 }
1426}
1427
1428static int mailmime_parse_with_default(const char * message, size_t length,
1429 size_t * index, int default_type,
1430 struct mailmime_content * content_type,
1431 struct mailmime_fields * mime_fields,
1432 struct mailmime ** result)
1433{
1434 size_t cur_token;
1435
1436 int body_type;
1437
1438 int encoding;
1439 struct mailmime_data * body;
1440 char * boundary;
1441 struct mailimf_fields * fields;
1442 clist * list;
1443 struct mailmime * msg_mime;
1444
1445 struct mailmime * mime;
1446
1447 int r;
1448 int res;
1449 struct mailmime_data * preamble;
1450 struct mailmime_data * epilogue;
1451
1452 /*
1453 note that when this function is called, content type is always detached,
1454 even if the function fails
1455 */
1456
1457 preamble = NULL;
1458 epilogue = NULL;
1459
1460 cur_token = * index;
1461
1462 /* get content type */
1463
1464 if (content_type == NULL) {
1465 if (mime_fields != NULL) {
1466 clistiter * cur;
1467
1468 for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ;
1469 cur = clist_next(cur)) {
1470 struct mailmime_field * field;
1471
1472 field = clist_content(cur);
1473 if (field->fld_type == MAILMIME_FIELD_TYPE) {
1474 content_type = field->fld_data.fld_content;
1475
1476 /* detach content type from list */
1477 field->fld_data.fld_content = NULL;
1478 clist_delete(mime_fields->fld_list, cur);
1479 mailmime_field_free(field);
1480 /*
1481 there may be a leak due to the detached content type
1482 in case the function fails
1483 */
1484 break;
1485 }
1486 }
1487 }
1488 }
1489
1490 /* set default type if no content type */
1491
1492 if (content_type == NULL) {
1493 /* content_type is detached, in any case, we will have to free it */
1494 if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) {
1495 content_type = mailmime_get_content_text();
1496 if (content_type == NULL) {
1497 res = MAILIMF_ERROR_MEMORY;
1498 goto err;
1499 }
1500 }
1501 else /* message */ {
1502 body_type = MAILMIME_MESSAGE;
1503
1504 content_type = mailmime_get_content_message();
1505 if (content_type == NULL) {
1506 res = MAILIMF_ERROR_MEMORY;
1507 goto err;
1508 }
1509 }
1510 }
1511
1512 /* get the body type */
1513
1514 boundary = NULL; /* XXX - removes a gcc warning */
1515
1516 switch (content_type->ct_type->tp_type) {
1517 case MAILMIME_TYPE_COMPOSITE_TYPE:
1518 switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) {
1519 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
1520 boundary = mailmime_extract_boundary(content_type);
1521
1522 if (boundary == NULL)
1523 body_type = MAILMIME_SINGLE;
1524 else
1525 body_type = MAILMIME_MULTIPLE;
1526 break;
1527
1528 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
1529
1530 if (strcasecmp(content_type->ct_subtype, "rfc822") == 0)
1531 body_type = MAILMIME_MESSAGE;
1532 else
1533 body_type = MAILMIME_SINGLE;
1534 break;
1535
1536 default:
1537 res = MAILIMF_ERROR_INVAL;
1538 goto free_content;
1539 }
1540 break;
1541
1542 default: /* MAILMIME_TYPE_DISCRETE_TYPE */
1543 body_type = MAILMIME_SINGLE;
1544 break;
1545 }
1546
1547 /* set body */
1548
1549 if (mime_fields != NULL)
1550 encoding = mailmime_transfer_encoding_get(mime_fields);
1551 else
1552 encoding = MAILMIME_MECHANISM_8BIT;
1553
1554 cur_token = * index;
1555 body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1,
1556 message + cur_token, length - cur_token,
1557 NULL);
1558 if (body == NULL) {
1559 res = MAILIMF_ERROR_MEMORY;
1560 goto free_content;
1561 }
1562
1563 /* in case of composite, parse the sub-part(s) */
1564
1565 list = NULL;
1566 msg_mime = NULL;
1567 fields = NULL;
1568
1569 switch (body_type) {
1570 case MAILMIME_MESSAGE:
1571 {
1572 struct mailmime_fields * submime_fields;
1573
1574 r = mailimf_envelope_and_optional_fields_parse(message, length,
1575 &cur_token, &fields);
1576 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1577 res = r;
1578 goto free_content;
1579 }
1580
1581 r = mailimf_crlf_parse(message, length, &cur_token);
1582 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1583 mailimf_fields_free(fields);
1584 res = r;
1585 goto free_content;
1586 }
1587
1588 submime_fields = NULL;
1589 r = mailmime_fields_parse(fields, &submime_fields);
1590 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1591 mailimf_fields_free(fields);
1592 res = r;
1593 goto free_content;
1594 }
1595
1596 remove_unparsed_mime_headers(fields);
1597
1598 r = mailmime_parse_with_default(message, length,
1599 &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1600 NULL, submime_fields, &msg_mime);
1601 if (r == MAILIMF_NO_ERROR) {
1602 /* do nothing */
1603 }
1604 else if (r == MAILIMF_ERROR_PARSE) {
1605 mailmime_fields_free(mime_fields);
1606 msg_mime = NULL;
1607 }
1608 else {
1609 mailmime_fields_free(mime_fields);
1610 res = r;
1611 goto free_content;
1612 }
1613 }
1614
1615 break;
1616
1617 case MAILMIME_MULTIPLE:
1618 {
1619 int default_subtype;
1620
1621 default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN;
1622 if (content_type != NULL)
1623 if (strcasecmp(content_type->ct_subtype, "digest") == 0)
1624 default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE;
1625
1626 cur_token = * index;
1627 r = mailmime_multipart_body_parse(message, length,
1628 &cur_token, boundary,
1629 default_subtype,
1630 &list, &preamble, &epilogue);
1631 if (r == MAILIMF_NO_ERROR) {
1632 /* do nothing */
1633 }
1634 else if (r == MAILIMF_ERROR_PARSE) {
1635 list = clist_new();
1636 if (list == NULL) {
1637 res = MAILIMF_ERROR_MEMORY;
1638 goto free_content;
1639 }
1640 }
1641 else {
1642 res = r;
1643 goto free_content;
1644 }
1645
1646 free(boundary);
1647 }
1648 break;
1649
1650 default: /* MAILMIME_SINGLE */
1651 /* do nothing */
1652 break;
1653 }
1654
1655 mime = mailmime_new(body_type, message, length,
1656 mime_fields, content_type,
1657 body, preamble, /* preamble */
1658 epilogue, /* epilogue */
1659 list, fields, msg_mime);
1660 if (mime == NULL) {
1661 res = MAILIMF_ERROR_MEMORY;
1662 goto free;
1663 }
1664
1665 * result = mime;
1666 * index = length;
1667
1668 return MAILIMF_NO_ERROR;
1669
1670 free:
1671 if (epilogue != NULL)
1672 mailmime_data_free(epilogue);
1673 if (preamble != NULL)
1674 mailmime_data_free(preamble);
1675 if (msg_mime != NULL)
1676 mailmime_free(msg_mime);
1677 if (list != NULL) {
1678 clist_foreach(list, (clist_func) mailmime_free, NULL);
1679 clist_free(list);
1680 }
1681 free_content:
1682 mailmime_content_free(content_type);
1683 err:
1684 return res;
1685}
1686
1687static int mailmime_get_section_list(struct mailmime * mime,
1688 clistiter * list, struct mailmime ** result)
1689{
1690 uint32_t id;
1691 struct mailmime * data;
1692 struct mailmime * submime;
1693
1694 if (list == NULL) {
1695 * result = mime;
1696 return MAILIMF_NO_ERROR;
1697 }
1698
1699 id = * ((uint32_t *) clist_content(list));
1700
1701 data = NULL;
1702 switch (mime->mm_type) {
1703 case MAILMIME_SINGLE:
1704 return MAILIMF_ERROR_INVAL;
1705
1706 case MAILMIME_MULTIPLE:
1707 data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1);
1708 if (data == NULL)
1709 return MAILIMF_ERROR_INVAL;
1710
1711 if (clist_next(list) != NULL)
1712 return mailmime_get_section_list(data, clist_next(list), result);
1713 else {
1714 * result = data;
1715 return MAILIMF_NO_ERROR;
1716 }
1717
1718 case MAILMIME_MESSAGE:
1719 submime = mime->mm_data.mm_message.mm_msg_mime;
1720 switch (submime->mm_type) {
1721 case MAILMIME_MULTIPLE:
1722 data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1);
1723 if (data == NULL)
1724 return MAILIMF_ERROR_INVAL;
1725 return mailmime_get_section_list(data, clist_next(list), result);
1726
1727 default:
1728 if (id != 1)
1729 return MAILIMF_ERROR_INVAL;
1730
1731 data = submime;
1732 if (data == NULL)
1733 return MAILIMF_ERROR_INVAL;
1734
1735 return mailmime_get_section_list(data, clist_next(list), result);
1736 }
1737 break;
1738
1739 default:
1740 return MAILIMF_ERROR_INVAL;
1741 }
1742}
1743
1744int mailmime_get_section(struct mailmime * mime,
1745 struct mailmime_section * section,
1746 struct mailmime ** result)
1747{
1748 return mailmime_get_section_list(mime,
1749 clist_begin(section->sec_list), result);
1750}
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766/* ************************************************************************* */
1767/* MIME part decoding */
1768
1769static inline signed char get_base64_value(char ch)
1770{
1771 if ((ch >= 'A') && (ch <= 'Z'))
1772 return ch - 'A';
1773 if ((ch >= 'a') && (ch <= 'z'))
1774 return ch - 'a' + 26;
1775 if ((ch >= '0') && (ch <= '9'))
1776 return ch - '0' + 52;
1777 switch (ch) {
1778 case '+':
1779 return 62;
1780 case '/':
1781 return 63;
1782 case '=': /* base64 padding */
1783 return -1;
1784 default:
1785 return -1;
1786 }
1787}
1788
1789int mailmime_base64_body_parse(const char * message, size_t length,
1790 size_t * index, char ** result,
1791 size_t * result_len)
1792{
1793 size_t cur_token;
1794 size_t i;
1795 char chunk[4];
1796 int chunk_index;
1797 char out[3];
1798 MMAPString * mmapstr;
1799 int res;
1800 int r;
1801 size_t written;
1802
1803 cur_token = * index;
1804 chunk_index = 0;
1805 written = 0;
1806
1807 mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4);
1808 if (mmapstr == NULL) {
1809 res = MAILIMF_ERROR_MEMORY;
1810 goto err;
1811 }
1812
1813 i = 0;
1814 while (1) {
1815 signed char value;
1816
1817 value = -1;
1818 while (value == -1) {
1819
1820 if (cur_token >= length)
1821 break;
1822
1823 value = get_base64_value(message[cur_token]);
1824 cur_token ++;
1825 }
1826
1827 if (value == -1)
1828 break;
1829
1830 chunk[chunk_index] = value;
1831 chunk_index ++;
1832
1833 if (chunk_index == 4) {
1834 out[0] = (chunk[0] << 2) | (chunk[1] >> 4);
1835 out[1] = (chunk[1] << 4) | (chunk[2] >> 2);
1836 out[2] = (chunk[2] << 6) | (chunk[3]);
1837
1838 chunk[0] = 0;
1839 chunk[1] = 0;
1840 chunk[2] = 0;
1841 chunk[3] = 0;
1842
1843 chunk_index = 0;
1844
1845 if (mmap_string_append_len(mmapstr, out, 3) == NULL) {
1846 res = MAILIMF_ERROR_MEMORY;
1847 goto free;
1848 }
1849 written += 3;
1850 }
1851 }
1852
1853 if (chunk_index != 0) {
1854 size_t len;
1855
1856 len = 0;
1857 out[0] = (chunk[0] << 2) | (chunk[1] >> 4);
1858 len ++;
1859
1860 if (chunk_index >= 3) {
1861 out[1] = (chunk[1] << 4) | (chunk[2] >> 2);
1862 len ++;
1863 }
1864
1865 if (mmap_string_append_len(mmapstr, out, len) == NULL) {
1866 res = MAILIMF_ERROR_MEMORY;
1867 goto free;
1868 }
1869 written += len;
1870 }
1871
1872 r = mmap_string_ref(mmapstr);
1873 if (r < 0) {
1874 res = MAILIMF_ERROR_MEMORY;
1875 goto free;
1876 }
1877
1878 * index = cur_token;
1879 * result = mmapstr->str;
1880 * result_len = written;
1881
1882 return MAILIMF_NO_ERROR;
1883
1884 free:
1885 mmap_string_free(mmapstr);
1886 err:
1887 return res;
1888}
1889
1890
1891
1892static inline int hexa_to_char(char hexdigit)
1893{
1894 if ((hexdigit >= '0') && (hexdigit <= '9'))
1895 return hexdigit - '0';
1896 if ((hexdigit >= 'a') && (hexdigit <= 'f'))
1897 return hexdigit - 'a' + 10;
1898 if ((hexdigit >= 'A') && (hexdigit <= 'F'))
1899 return hexdigit - 'A' + 10;
1900 return 0;
1901}
1902
1903static inline char to_char(const char * hexa)
1904{
1905 return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]);
1906}
1907
1908enum {
1909 STATE_NORMAL,
1910 STATE_CODED,
1911 STATE_OUT,
1912 STATE_CR,
1913};
1914
1915
1916static int write_decoded_qp(MMAPString * mmapstr,
1917 const char * start, size_t count)
1918{
1919 if (mmap_string_append_len(mmapstr, start, count) == NULL)
1920 return MAILIMF_ERROR_MEMORY;
1921
1922 return MAILIMF_NO_ERROR;
1923}
1924
1925
1926#define WRITE_MAX_QP 512
1927
1928int mailmime_quoted_printable_body_parse(const char * message, size_t length,
1929 size_t * index, char ** result,
1930 size_t * result_len, int in_header)
1931{
1932 size_t cur_token;
1933 int state;
1934 int r;
1935 char ch;
1936 size_t count;
1937 const char * start;
1938 MMAPString * mmapstr;
1939 int res;
1940 size_t written;
1941
1942 state = STATE_NORMAL;
1943 cur_token = * index;
1944
1945 count = 0;
1946 start = message + cur_token;
1947 written = 0;
1948
1949 mmapstr = mmap_string_sized_new(length - cur_token);
1950 if (mmapstr == NULL) {
1951 res = MAILIMF_ERROR_MEMORY;
1952 goto err;
1953 }
1954
1955#if 0
1956 if (length >= 1) {
1957 if (message[length - 1] == '\n') {
1958 length --;
1959 if (length >= 1)
1960 if (message[length - 1] == '\r') {
1961 length --;
1962 }
1963 }
1964 }
1965#endif
1966
1967 while (state != STATE_OUT) {
1968
1969 if (cur_token >= length) {
1970 state = STATE_OUT;
1971 break;
1972 }
1973
1974 switch (state) {
1975
1976 case STATE_CODED:
1977
1978 if (count > 0) {
1979 r = write_decoded_qp(mmapstr, start, count);
1980 if (r != MAILIMF_NO_ERROR) {
1981 res = r;
1982 goto free;
1983 }
1984 written += count;
1985 count = 0;
1986 }
1987
1988 switch (message[cur_token]) {
1989 case '=':
1990 if (cur_token + 1 >= length) {
1991 /* error but ignore it */
1992 state = STATE_NORMAL;
1993 start = message + cur_token;
1994 cur_token ++;
1995 count ++;
1996 break;
1997 }
1998
1999 switch (message[cur_token + 1]) {
2000
2001 case '\n':
2002 cur_token += 2;
2003
2004 start = message + cur_token;
2005
2006 state = STATE_NORMAL;
2007 break;
2008
2009 case '\r':
2010 if (cur_token + 2 >= length) {
2011 state = STATE_OUT;
2012 break;
2013 }
2014
2015 if (message[cur_token + 2] == '\n')
2016 cur_token += 3;
2017 else
2018 cur_token += 2;
2019
2020 start = message + cur_token;
2021
2022 state = STATE_NORMAL;
2023
2024 break;
2025
2026 default:
2027 if (cur_token + 2 >= length) {
2028 /* error but ignore it */
2029 cur_token ++;
2030
2031 start = message + cur_token;
2032
2033 count ++;
2034 state = STATE_NORMAL;
2035 break;
2036 }
2037
2038#if 0
2039 /* flush before writing additionnal information */
2040 r = write_decoded_qp(mmapstr, start, count);
2041 if (r != MAILIMF_NO_ERROR) {
2042 res = r;
2043 goto free;
2044 }
2045 written += count;
2046 count = 0;
2047#endif
2048
2049 ch = to_char(message + cur_token + 1);
2050
2051 if (mmap_string_append_c(mmapstr, ch) == NULL) {
2052 res = MAILIMF_ERROR_MEMORY;
2053 goto free;
2054 }
2055
2056 cur_token += 3;
2057 written ++;
2058
2059 start = message + cur_token;
2060
2061 state = STATE_NORMAL;
2062 break;
2063 }
2064 break;
2065 }
2066 break; /* end of STATE_ENCODED */
2067
2068 case STATE_NORMAL:
2069
2070 switch (message[cur_token]) {
2071
2072 case '=':
2073 state = STATE_CODED;
2074 break;
2075
2076 case '\n':
2077 /* flush before writing additionnal information */
2078 if (count > 0) {
2079 r = write_decoded_qp(mmapstr, start, count);
2080 if (r != MAILIMF_NO_ERROR) {
2081 res = r;
2082 goto free;
2083 }
2084 written += count;
2085
2086 count = 0;
2087 }
2088
2089 r = write_decoded_qp(mmapstr, "\r\n", 2);
2090 if (r != MAILIMF_NO_ERROR) {
2091 res = r;
2092 goto free;
2093 }
2094 written += 2;
2095 cur_token ++;
2096 start = message + cur_token;
2097 break;
2098
2099 case '\r':
2100 state = STATE_CR;
2101 cur_token ++;
2102 break;
2103
2104 case '_':
2105 if (in_header) {
2106 if (count > 0) {
2107 r = write_decoded_qp(mmapstr, start, count);
2108 if (r != MAILIMF_NO_ERROR) {
2109 res = r;
2110 goto free;
2111 }
2112 written += count;
2113 count = 0;
2114 }
2115
2116 if (mmap_string_append_c(mmapstr, ' ') == NULL) {
2117 res = MAILIMF_ERROR_MEMORY;
2118 goto free;
2119 }
2120
2121 written ++;
2122 cur_token ++;
2123 start = message + cur_token;
2124
2125 break;
2126 }
2127 /* WARINING : must be followed by switch default action */
2128
2129 default:
2130 if (count >= WRITE_MAX_QP) {
2131 r = write_decoded_qp(mmapstr, start, count);
2132 if (r != MAILIMF_NO_ERROR) {
2133 res = r;
2134 goto free;
2135 }
2136 written += count;
2137 count = 0;
2138 start = message + cur_token;
2139 }
2140
2141 count ++;
2142 cur_token ++;
2143 break;
2144 }
2145 break; /* end of STATE_NORMAL */
2146
2147 case STATE_CR:
2148 switch (message[cur_token]) {
2149
2150 case '\n':
2151 /* flush before writing additionnal information */
2152 if (count > 0) {
2153 r = write_decoded_qp(mmapstr, start, count);
2154 if (r != MAILIMF_NO_ERROR) {
2155 res = r;
2156 goto free;
2157 }
2158 written += count;
2159 count = 0;
2160 }
2161
2162 r = write_decoded_qp(mmapstr, "\r\n", 2);
2163 if (r != MAILIMF_NO_ERROR) {
2164 res = r;
2165 goto free;
2166 }
2167 written += 2;
2168 cur_token ++;
2169 start = message + cur_token;
2170 state = STATE_NORMAL;
2171 break;
2172
2173 default:
2174 /* flush before writing additionnal information */
2175 if (count > 0) {
2176 r = write_decoded_qp(mmapstr, start, count);
2177 if (r != MAILIMF_NO_ERROR) {
2178 res = r;
2179 goto free;
2180 }
2181 written += count;
2182 count = 0;
2183 }
2184
2185 start = message + cur_token;
2186
2187 r = write_decoded_qp(mmapstr, "\r\n", 2);
2188 if (r != MAILIMF_NO_ERROR) {
2189 res = r;
2190 goto free;
2191 }
2192 written += 2;
2193 state = STATE_NORMAL;
2194 }
2195 break; /* end of STATE_CR */
2196 }
2197 }
2198
2199 if (count > 0) {
2200 r = write_decoded_qp(mmapstr, start, count);
2201 if (r != MAILIMF_NO_ERROR) {
2202 res = r;
2203 goto free;
2204 }
2205 written += count;
2206 count = 0;
2207 }
2208
2209 r = mmap_string_ref(mmapstr);
2210 if (r < 0) {
2211 res = MAILIMF_ERROR_MEMORY;
2212 goto free;
2213 }
2214
2215 * index = cur_token;
2216 * result = mmapstr->str;
2217 * result_len = written;
2218
2219 return MAILIMF_NO_ERROR;
2220
2221 free:
2222 mmap_string_free(mmapstr);
2223 err:
2224 return res;
2225}
2226
2227int mailmime_binary_body_parse(const char * message, size_t length,
2228 size_t * index, char ** result,
2229 size_t * result_len)
2230{
2231 MMAPString * mmapstr;
2232 size_t cur_token;
2233 int r;
2234 int res;
2235
2236 cur_token = * index;
2237
2238 if (length >= 1) {
2239 if (message[length - 1] == '\n') {
2240 length --;
2241 if (length >= 1)
2242 if (message[length - 1] == '\r')
2243 length --;
2244 }
2245 }
2246
2247 mmapstr = mmap_string_new_len(message + cur_token, length - cur_token);
2248 if (mmapstr == NULL) {
2249 res = MAILIMF_ERROR_MEMORY;
2250 goto err;
2251 }
2252
2253 r = mmap_string_ref(mmapstr);
2254 if (r < 0) {
2255 res = MAILIMF_ERROR_MEMORY;
2256 goto free;
2257 }
2258
2259 * index = length;
2260 * result = mmapstr->str;
2261 * result_len = length - cur_token;
2262
2263 return MAILIMF_NO_ERROR;
2264
2265 free:
2266 mmap_string_free(mmapstr);
2267 err:
2268 return res;
2269}
2270
2271
2272int mailmime_part_parse(const char * message, size_t length,
2273 size_t * index,
2274 int encoding, char ** result, size_t * result_len)
2275{
2276 switch (encoding) {
2277 case MAILMIME_MECHANISM_BASE64:
2278 return mailmime_base64_body_parse(message, length, index,
2279 result, result_len);
2280
2281 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
2282 return mailmime_quoted_printable_body_parse(message, length, index,
2283 result, result_len, FALSE);
2284
2285 case MAILMIME_MECHANISM_7BIT:
2286 case MAILMIME_MECHANISM_8BIT:
2287 case MAILMIME_MECHANISM_BINARY:
2288 default:
2289 return mailmime_binary_body_parse(message, length, index,
2290 result, result_len);
2291 }
2292}
2293
2294int mailmime_get_section_id(struct mailmime * mime,
2295 struct mailmime_section ** result)
2296{
2297 clist * list;
2298 int res;
2299 struct mailmime_section * section_id;
2300 int r;
2301
2302 if (mime->mm_parent == NULL) {
2303 list = clist_new();
2304 if (list == NULL) {
2305 res = MAILIMF_ERROR_MEMORY;
2306 goto err;
2307 }
2308
2309 section_id = mailmime_section_new(list);
2310 if (section_id == NULL) {
2311 res = MAILIMF_ERROR_MEMORY;
2312 goto err;
2313 }
2314 }
2315 else {
2316 uint32_t id;
2317 uint32_t * p_id;
2318 clistiter * cur;
2319 struct mailmime * parent;
2320
2321 r = mailmime_get_section_id(mime->mm_parent, &section_id);
2322 if (r != MAILIMF_NO_ERROR) {
2323 res = r;
2324 goto err;
2325 }
2326
2327 parent = mime->mm_parent;
2328 switch (parent->mm_type) {
2329 case MAILMIME_MULTIPLE:
2330 id = 1;
2331 for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ;
2332 cur != NULL ; cur = clist_next(cur)) {
2333 if (clist_content(cur) == mime)
2334 break;
2335 id ++;
2336 }
2337
2338 p_id = malloc(sizeof(* p_id));
2339 if (p_id == NULL) {
2340 res = MAILIMF_ERROR_MEMORY;
2341 goto free;
2342 }
2343 * p_id = id;
2344
2345 r = clist_append(section_id->sec_list, p_id);
2346 if (r < 0) {
2347 free(p_id);
2348 res = MAILIMF_ERROR_MEMORY;
2349 goto free;
2350 }
2351 break;
2352
2353 case MAILMIME_MESSAGE:
2354 if ((mime->mm_type == MAILMIME_SINGLE) ||
2355 (mime->mm_type == MAILMIME_MESSAGE)) {
2356 p_id = malloc(sizeof(* p_id));
2357 if (p_id == NULL) {
2358 res = MAILIMF_ERROR_MEMORY;
2359 goto free;
2360 }
2361 * p_id = 1;
2362
2363 r = clist_append(section_id->sec_list, p_id);
2364 if (r < 0) {
2365 free(p_id);
2366 res = MAILIMF_ERROR_MEMORY;
2367 goto free;
2368 }
2369 }
2370 }
2371 }
2372
2373 * result = section_id;
2374
2375 return MAILIMF_NO_ERROR;
2376
2377 free:
2378 mailmime_section_free(section_id);
2379 err:
2380 return res;
2381}
diff --git a/libetpan/src/low-level/mime/mailmime_content.h b/libetpan/src/low-level/mime/mailmime_content.h
new file mode 100644
index 0000000..989e515
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_content.h
@@ -0,0 +1,89 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_CONTENT_H
37
38#define MAILMIME_CONTENT_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46char * mailmime_content_charset_get(struct mailmime_content * content);
47
48char * mailmime_content_param_get(struct mailmime_content * content,
49 char * name);
50
51int mailmime_parse(const char * message, size_t length,
52 size_t * index, struct mailmime ** result);
53
54int mailmime_get_section(struct mailmime * mime,
55 struct mailmime_section * section,
56 struct mailmime ** result);
57
58
59char * mailmime_extract_boundary(struct mailmime_content * content_type);
60
61
62/* decode */
63
64int mailmime_base64_body_parse(const char * message, size_t length,
65 size_t * index, char ** result,
66 size_t * result_len);
67
68int mailmime_quoted_printable_body_parse(const char * message, size_t length,
69 size_t * index, char ** result,
70 size_t * result_len, int in_header);
71
72
73int mailmime_binary_body_parse(const char * message, size_t length,
74 size_t * index, char ** result,
75 size_t * result_len);
76
77int mailmime_part_parse(const char * message, size_t length,
78 size_t * index,
79 int encoding, char ** result, size_t * result_len);
80
81
82int mailmime_get_section_id(struct mailmime * mime,
83 struct mailmime_section ** result);
84
85#ifdef __cplusplus
86}
87#endif
88
89#endif
diff --git a/libetpan/src/low-level/mime/mailmime_decode.c b/libetpan/src/low-level/mime/mailmime_decode.c
new file mode 100644
index 0000000..715ddad
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_decode.c
@@ -0,0 +1,544 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three:
38 Message Header Extensions for Non-ASCII Text
39*/
40
41#include "mailmime_decode.h"
42
43#include <ctype.h>
44#include <unistd.h>
45#include <sys/mman.h>
46#include <string.h>
47#include <stdlib.h>
48
49#include "mailmime_content.h"
50
51#include "charconv.h"
52#include "mmapstring.h"
53#include "mailimf.h"
54
55#ifndef TRUE
56#define TRUE 1
57#endif
58
59#ifndef FALSE
60#define FALSE 0
61#endif
62
63static int mailmime_charset_parse(const char * message, size_t length,
64 size_t * index, char ** charset);
65
66enum {
67 MAILMIME_ENCODING_B,
68 MAILMIME_ENCODING_Q
69};
70
71static int mailmime_encoding_parse(const char * message, size_t length,
72 size_t * index, int * result);
73
74static int mailmime_etoken_parse(const char * message, size_t length,
75 size_t * index, char ** result);
76
77static int
78mailmime_non_encoded_word_parse(const char * message, size_t length,
79 size_t * index,
80 char ** result);
81
82static int
83mailmime_encoded_word_parse(const char * message, size_t length,
84 size_t * index,
85 struct mailmime_encoded_word ** result);
86
87
88enum {
89 TYPE_ERROR,
90 TYPE_WORD,
91 TYPE_ENCODED_WORD,
92};
93
94int mailmime_encoded_phrase_parse(const char * default_fromcode,
95 const char * message, size_t length,
96 size_t * index, const char * tocode,
97 char ** result)
98{
99 MMAPString * gphrase;
100 struct mailmime_encoded_word * word;
101 int first;
102 size_t cur_token;
103 int r;
104 int res;
105 char * str;
106 char * wordutf8;
107 int type;
108
109 cur_token = * index;
110
111 gphrase = mmap_string_new("");
112 if (gphrase == NULL) {
113 res = MAILIMF_ERROR_MEMORY;
114 goto err;
115 }
116
117 first = TRUE;
118
119 type = TYPE_ERROR; /* XXX - removes a gcc warning */
120
121 while (1) {
122
123 r = mailmime_encoded_word_parse(message, length, &cur_token, &word);
124 if (r == MAILIMF_NO_ERROR) {
125 if (!first) {
126 if (type != TYPE_ENCODED_WORD) {
127 if (mmap_string_append_c(gphrase, ' ') == NULL) {
128 mailmime_encoded_word_free(word);
129 res = MAILIMF_ERROR_MEMORY;
130 goto free;
131 }
132 }
133 }
134 type = TYPE_ENCODED_WORD;
135 wordutf8 = NULL;
136 r = charconv(tocode, word->wd_charset, word->wd_text,
137 strlen(word->wd_text), &wordutf8);
138 switch (r) {
139 case MAIL_CHARCONV_ERROR_MEMORY:
140 mailmime_encoded_word_free(word);
141 res = MAILIMF_ERROR_MEMORY;
142 goto free;
143
144 case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET:
145 case MAIL_CHARCONV_ERROR_CONV:
146 mailmime_encoded_word_free(word);
147 res = MAILIMF_ERROR_PARSE;
148 goto free;
149 }
150
151 if (wordutf8 != NULL) {
152 if (mmap_string_append(gphrase, wordutf8) == NULL) {
153 mailmime_encoded_word_free(word);
154 free(wordutf8);
155 res = MAILIMF_ERROR_MEMORY;
156 goto free;
157 }
158 free(wordutf8);
159 }
160 mailmime_encoded_word_free(word);
161 first = FALSE;
162 }
163 else if (r == MAILIMF_ERROR_PARSE) {
164 /* do nothing */
165 }
166 else {
167 res = r;
168 goto free;
169 }
170
171 if (r == MAILIMF_ERROR_PARSE) {
172 char * raw_word;
173
174 r = mailmime_non_encoded_word_parse(message, length,
175 &cur_token, &raw_word);
176 if (r == MAILIMF_NO_ERROR) {
177 if (!first) {
178 if (mmap_string_append_c(gphrase, ' ') == NULL) {
179 free(raw_word);
180 res = MAILIMF_ERROR_MEMORY;
181 goto free;
182 }
183 }
184 type = TYPE_WORD;
185
186 wordutf8 = NULL;
187 r = charconv(tocode, default_fromcode, raw_word,
188 strlen(raw_word), &wordutf8);
189
190 switch (r) {
191 case MAIL_CHARCONV_ERROR_MEMORY:
192 free(raw_word);
193 res = MAILIMF_ERROR_MEMORY;
194 goto free;
195
196 case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET:
197 case MAIL_CHARCONV_ERROR_CONV:
198 free(raw_word);
199 res = MAILIMF_ERROR_PARSE;
200 goto free;
201 }
202
203 if (mmap_string_append(gphrase, wordutf8) == NULL) {
204 free(wordutf8);
205 free(raw_word);
206 res = MAILIMF_ERROR_MEMORY;
207 goto free;
208 }
209
210 free(wordutf8);
211 free(raw_word);
212 first = FALSE;
213 }
214 else if (r == MAILIMF_ERROR_PARSE) {
215 break;
216 }
217 else {
218 res = r;
219 goto free;
220 }
221 }
222 }
223
224 if (first) {
225 res = MAILIMF_ERROR_PARSE;
226 goto free;
227 }
228
229 str = strdup(gphrase->str);
230 if (str == NULL) {
231 res = MAILIMF_ERROR_MEMORY;
232 goto free;
233 }
234 mmap_string_free(gphrase);
235
236 * result = str;
237 * index = cur_token;
238
239 return MAILIMF_NO_ERROR;
240
241 free:
242 mmap_string_free(gphrase);
243 err:
244 return res;
245}
246
247static int
248mailmime_non_encoded_word_parse(const char * message, size_t length,
249 size_t * index,
250 char ** result)
251{
252 int end;
253 size_t cur_token;
254 int res;
255 char * text;
256 int r;
257 size_t begin;
258
259 cur_token = * index;
260
261 r = mailimf_fws_parse(message, length, &cur_token);
262 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
263 res = r;
264 goto err;
265 }
266
267 begin = cur_token;
268
269 end = FALSE;
270 while (1) {
271 if (cur_token >= length)
272 break;
273
274 switch (message[cur_token]) {
275 case ' ':
276 case '\t':
277 case '\r':
278 case '\n':
279 end = TRUE;
280 break;
281 }
282
283 if (end)
284 break;
285
286 cur_token ++;
287 }
288
289 if (cur_token - begin == 0) {
290 res = MAILIMF_ERROR_PARSE;
291 goto err;
292 }
293
294 text = malloc(cur_token - begin + 1);
295 if (text == NULL) {
296 res = MAILIMF_ERROR_MEMORY;
297 goto err;
298 }
299
300 memcpy(text, message + begin, cur_token - begin);
301 text[cur_token - begin] = '\0';
302
303 * index = cur_token;
304 * result = text;
305
306 return MAILIMF_NO_ERROR;
307
308 err:
309 return res;
310}
311
312static int mailmime_encoded_word_parse(const char * message, size_t length,
313 size_t * index,
314 struct mailmime_encoded_word ** result)
315{
316 size_t cur_token;
317 char * charset;
318 int encoding;
319 char * text;
320 size_t end_encoding;
321 char * decoded;
322 size_t decoded_len;
323 struct mailmime_encoded_word * ew;
324 int r;
325 int res;
326 int opening_quote;
327 int end;
328
329 cur_token = * index;
330
331 r = mailimf_fws_parse(message, length, &cur_token);
332 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
333 res = r;
334 goto err;
335 }
336
337 opening_quote = FALSE;
338 r = mailimf_char_parse(message, length, &cur_token, '\"');
339 if (r == MAILIMF_NO_ERROR) {
340 opening_quote = TRUE;
341 }
342 else if (r == MAILIMF_ERROR_PARSE) {
343 /* do nothing */
344 }
345 else {
346 res = r;
347 goto err;
348 }
349
350 r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?");
351 if (r != MAILIMF_NO_ERROR) {
352 res = r;
353 goto err;
354 }
355
356 r = mailmime_charset_parse(message, length, &cur_token, &charset);
357 if (r != MAILIMF_NO_ERROR) {
358 res = r;
359 goto err;
360 }
361
362 r = mailimf_char_parse(message, length, &cur_token, '?');
363 if (r != MAILIMF_NO_ERROR) {
364 res = r;
365 goto free_charset;
366 }
367
368 r = mailmime_encoding_parse(message, length, &cur_token, &encoding);
369 if (r != MAILIMF_NO_ERROR) {
370 res = r;
371 goto free_charset;
372 }
373
374 r = mailimf_char_parse(message, length, &cur_token, '?');
375 if (r != MAILIMF_NO_ERROR) {
376 res = r;
377 goto free_charset;
378 }
379
380 end = FALSE;
381 end_encoding = cur_token;
382 while (1) {
383 if (end_encoding >= length)
384 break;
385
386 switch (message[end_encoding]) {
387 case '?':
388#if 0
389 case ' ':
390#endif
391 end = TRUE;
392 break;
393 }
394
395 if (end)
396 break;
397
398 end_encoding ++;
399 }
400
401 decoded_len = 0;
402 decoded = NULL;
403 switch (encoding) {
404 case MAILMIME_ENCODING_B:
405 r = mailmime_base64_body_parse(message, end_encoding,
406 &cur_token, &decoded,
407 &decoded_len);
408
409 if (r != MAILIMF_NO_ERROR) {
410 res = r;
411 goto free_charset;
412 }
413 break;
414 case MAILMIME_ENCODING_Q:
415 r = mailmime_quoted_printable_body_parse(message, end_encoding,
416 &cur_token, &decoded,
417 &decoded_len, TRUE);
418
419 if (r != MAILIMF_NO_ERROR) {
420 res = r;
421 goto free_charset;
422 }
423
424 break;
425 }
426
427 text = malloc(decoded_len + 1);
428 if (text == NULL) {
429 res = MAILIMF_ERROR_MEMORY;
430 goto free_charset;
431 }
432
433 if (decoded_len > 0)
434 memcpy(text, decoded, decoded_len);
435 text[decoded_len] = '\0';
436
437 mailmime_decoded_part_free(decoded);
438
439 r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?=");
440 if (r != MAILIMF_NO_ERROR) {
441 res = r;
442 goto free_encoded_text;
443 }
444
445 if (opening_quote) {
446 r = mailimf_char_parse(message, length, &cur_token, '\"');
447 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
448 res = r;
449 goto free_encoded_text;
450 }
451 }
452
453 ew = mailmime_encoded_word_new(charset, text);
454 if (ew == NULL) {
455 res = MAILIMF_ERROR_MEMORY;
456 goto free_encoded_text;
457 }
458
459 * result = ew;
460 * index = cur_token;
461
462 return MAILIMF_NO_ERROR;
463
464 free_encoded_text:
465 mailmime_encoded_text_free(text);
466 free_charset:
467 mailmime_charset_free(charset);
468 err:
469 return res;
470}
471
472static int mailmime_charset_parse(const char * message, size_t length,
473 size_t * index, char ** charset)
474{
475 return mailmime_etoken_parse(message, length, index, charset);
476}
477
478static int mailmime_encoding_parse(const char * message, size_t length,
479 size_t * index, int * result)
480{
481 size_t cur_token;
482 int encoding;
483
484 cur_token = * index;
485
486 if (cur_token >= length)
487 return MAILIMF_ERROR_PARSE;
488
489 switch ((char) toupper((unsigned char) message[cur_token])) {
490 case 'Q':
491 encoding = MAILMIME_ENCODING_Q;
492 break;
493 case 'B':
494 encoding = MAILMIME_ENCODING_B;
495 break;
496 default:
497 return MAILIMF_ERROR_INVAL;
498 }
499
500 cur_token ++;
501
502 * result = encoding;
503 * index = cur_token;
504
505 return MAILIMF_NO_ERROR;
506}
507
508int is_etoken_char(char ch)
509{
510 unsigned char uch = ch;
511
512 if (uch < 31)
513 return FALSE;
514
515 switch (uch) {
516 case ' ':
517 case '(':
518 case ')':
519 case '<':
520 case '>':
521 case '@':
522 case ',':
523 case ';':
524 case ':':
525 case '"':
526 case '/':
527 case '[':
528 case ']':
529 case '?':
530 case '.':
531 case '=':
532 return FALSE;
533 }
534
535 return TRUE;
536}
537
538static int mailmime_etoken_parse(const char * message, size_t length,
539 size_t * index, char ** result)
540{
541 return mailimf_custom_string_parse(message, length,
542 index, result,
543 is_etoken_char);
544}
diff --git a/libetpan/src/low-level/mime/mailmime_decode.h b/libetpan/src/low-level/mime/mailmime_decode.h
new file mode 100644
index 0000000..7b9d693
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_decode.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_DECODE_H
37
38#define MAILMIME_DECODE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_encoded_phrase_parse(const char * default_fromcode,
47 const char * message, size_t length,
48 size_t * index, const char * tocode,
49 char ** result);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/src/low-level/mime/mailmime_disposition.c b/libetpan/src/low-level/mime/mailmime_disposition.c
new file mode 100644
index 0000000..eb1d846
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_disposition.c
@@ -0,0 +1,595 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_disposition.h"
37#include "mailmime.h"
38
39#include <ctype.h>
40#include <stdlib.h>
41
42static int
43mailmime_disposition_parm_parse(const char * message, size_t length,
44 size_t * index,
45 struct mailmime_disposition_parm **
46 result);
47
48static int
49mailmime_creation_date_parm_parse(const char * message, size_t length,
50 size_t * index, char ** result);
51
52static int
53mailmime_filename_parm_parse(const char * message, size_t length,
54 size_t * index, char ** result);
55
56static int
57mailmime_modification_date_parm_parse(const char * message, size_t length,
58 size_t * index, char ** result);
59
60static int
61mailmime_read_date_parm_parse(const char * message, size_t length,
62 size_t * index, char ** result);
63
64static int
65mailmime_size_parm_parse(const char * message, size_t length,
66 size_t * index, size_t * result);
67
68static int
69mailmime_quoted_date_time_parse(const char * message, size_t length,
70 size_t * index, char ** result);
71
72/*
73 disposition := "Content-Disposition" ":"
74 disposition-type
75 *(";" disposition-parm)
76
77*/
78
79
80int mailmime_disposition_parse(const char * message, size_t length,
81 size_t * index,
82 struct mailmime_disposition ** result)
83{
84 size_t final_token;
85 size_t cur_token;
86 struct mailmime_disposition_type * dsp_type;
87 clist * list;
88 struct mailmime_disposition * dsp;
89 int r;
90 int res;
91
92 cur_token = * index;
93
94 r = mailmime_disposition_type_parse(message, length, &cur_token,
95 &dsp_type);
96 if (r != MAILIMF_NO_ERROR) {
97 res = r;
98 goto err;
99 }
100
101 list = clist_new();
102 if (list == NULL) {
103 res = MAILIMF_ERROR_MEMORY;
104 goto free_type;
105 }
106
107 while (1) {
108 struct mailmime_disposition_parm * param;
109
110 final_token = cur_token;
111 r = mailimf_unstrict_char_parse(message, length, &cur_token, ';');
112 if (r == MAILIMF_NO_ERROR) {
113 /* do nothing */
114 }
115 else if (r == MAILIMF_ERROR_PARSE) {
116 break;
117 }
118 else {
119 res = r;
120 goto free_list;
121 }
122
123 r = mailmime_disposition_parm_parse(message, length, &cur_token, &param);
124 if (r == MAILIMF_NO_ERROR) {
125 /* do nothing */
126 }
127 else if (r == MAILIMF_ERROR_PARSE) {
128 cur_token = final_token;
129 break;
130 }
131 else {
132 res = r;
133 goto free_list;
134 }
135
136 r = clist_append(list, param);
137 if (r < 0) {
138 res = MAILIMF_ERROR_MEMORY;
139 goto free_list;
140 }
141 }
142
143 dsp = mailmime_disposition_new(dsp_type, list);
144 if (dsp == NULL) {
145 res = MAILIMF_ERROR_MEMORY;
146 goto free_list;
147 }
148
149 * result = dsp;
150 * index = cur_token;
151
152 return MAILIMF_NO_ERROR;
153
154 free_list:
155 clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL);
156 clist_free(list);
157 free_type:
158 mailmime_disposition_type_free(dsp_type);
159 err:
160 return res;
161}
162
163 /*
164 disposition-type := "inline"
165 / "attachment"
166 / extension-token
167 ; values are not case-sensitive
168
169*/
170
171
172
173int
174mailmime_disposition_type_parse(const char * message, size_t length,
175 size_t * index,
176 struct mailmime_disposition_type ** result)
177{
178 size_t cur_token;
179 int type;
180 char * extension;
181 struct mailmime_disposition_type * dsp_type;
182 int r;
183 int res;
184
185 cur_token = * index;
186
187 r = mailimf_cfws_parse(message, length, &cur_token);
188 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
189 res = r;
190 goto err;
191 }
192
193 type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */
194
195 extension = NULL;
196 r = mailimf_token_case_insensitive_parse(message, length,
197 &cur_token, "inline");
198 if (r == MAILIMF_NO_ERROR)
199 type = MAILMIME_DISPOSITION_TYPE_INLINE;
200
201 if (r == MAILIMF_ERROR_PARSE) {
202 r = mailimf_token_case_insensitive_parse(message, length,
203 &cur_token, "attachment");
204 if (r == MAILIMF_NO_ERROR)
205 type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT;
206 }
207
208 if (r == MAILIMF_ERROR_PARSE) {
209 r = mailmime_extension_token_parse(message, length, &cur_token,
210 &extension);
211 if (r == MAILIMF_NO_ERROR)
212 type = MAILMIME_DISPOSITION_TYPE_EXTENSION;
213 }
214
215 if (r != MAILIMF_NO_ERROR) {
216 res = r;
217 goto err;
218 }
219
220 dsp_type = mailmime_disposition_type_new(type, extension);
221 if (dsp_type == NULL) {
222 res = MAILIMF_ERROR_MEMORY;
223 goto free;
224 }
225
226 * result = dsp_type;
227 * index = cur_token;
228
229 return MAILIMF_NO_ERROR;
230
231 free:
232 if (extension != NULL)
233 free(extension);
234 err:
235 return res;
236}
237
238/*
239 disposition-parm := filename-parm
240 / creation-date-parm
241 / modification-date-parm
242 / read-date-parm
243 / size-parm
244 / parameter
245*/
246
247
248int mailmime_disposition_guess_type(const char * message, size_t length,
249 size_t index)
250{
251 if (index >= length)
252 return MAILMIME_DISPOSITION_PARM_PARAMETER;
253
254 switch ((char) toupper((unsigned char) message[index])) {
255 case 'F':
256 return MAILMIME_DISPOSITION_PARM_FILENAME;
257 case 'C':
258 return MAILMIME_DISPOSITION_PARM_CREATION_DATE;
259 case 'M':
260 return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE;
261 case 'R':
262 return MAILMIME_DISPOSITION_PARM_READ_DATE;
263 case 'S':
264 return MAILMIME_DISPOSITION_PARM_SIZE;
265 default:
266 return MAILMIME_DISPOSITION_PARM_PARAMETER;
267 }
268}
269
270static int
271mailmime_disposition_parm_parse(const char * message, size_t length,
272 size_t * index,
273 struct mailmime_disposition_parm **
274 result)
275{
276 char * filename;
277 char * creation_date;
278 char * modification_date;
279 char * read_date;
280 size_t size;
281 struct mailmime_parameter * parameter;
282 size_t cur_token;
283 struct mailmime_disposition_parm * dsp_parm;
284 int type;
285 int guessed_type;
286 int r;
287 int res;
288
289 cur_token = * index;
290
291 filename = NULL;
292 creation_date = NULL;
293 modification_date = NULL;
294 read_date = NULL;
295 size = 0;
296 parameter = NULL;
297
298 r = mailimf_cfws_parse(message, length, &cur_token);
299 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
300 res = r;
301 goto err;
302 }
303
304 guessed_type = mailmime_disposition_guess_type(message, length, cur_token);
305
306 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
307
308 switch (guessed_type) {
309 case MAILMIME_DISPOSITION_PARM_FILENAME:
310 r = mailmime_filename_parm_parse(message, length, &cur_token,
311 &filename);
312 if (r == MAILIMF_NO_ERROR)
313 type = guessed_type;
314 else if (r == MAILIMF_ERROR_PARSE) {
315 /* do nothing */
316 }
317 else {
318 res = r;
319 goto err;
320 }
321 break;
322
323 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
324 r = mailmime_creation_date_parm_parse(message, length, &cur_token,
325 &creation_date);
326 if (r == MAILIMF_NO_ERROR)
327 type = guessed_type;
328 else if (r == MAILIMF_ERROR_PARSE) {
329 /* do nothing */
330 }
331 else {
332 res = r;
333 goto err;
334 }
335 break;
336
337 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
338 r = mailmime_modification_date_parm_parse(message, length, &cur_token,
339 &modification_date);
340 if (r == MAILIMF_NO_ERROR)
341 type = guessed_type;
342 else if (r == MAILIMF_ERROR_PARSE) {
343 /* do nothing */
344 }
345 else {
346 res = r;
347 goto err;
348 }
349 break;
350
351 case MAILMIME_DISPOSITION_PARM_READ_DATE:
352 r = mailmime_read_date_parm_parse(message, length, &cur_token,
353 &read_date);
354 if (r == MAILIMF_NO_ERROR)
355 type = guessed_type;
356 else if (r == MAILIMF_ERROR_PARSE) {
357 /* do nothing */
358 }
359 else {
360 res = r;
361 goto err;
362 }
363 break;
364
365 case MAILMIME_DISPOSITION_PARM_SIZE:
366 r = mailmime_size_parm_parse(message, length, &cur_token,
367 &size);
368 if (r == MAILIMF_NO_ERROR)
369 type = guessed_type;
370 else if (r == MAILIMF_ERROR_PARSE) {
371 /* do nothing */
372 }
373 else {
374 res = r;
375 goto err;
376 }
377 break;
378 }
379
380 if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
381 r = mailmime_parameter_parse(message, length, &cur_token,
382 &parameter);
383 if (r != MAILIMF_NO_ERROR) {
384 type = guessed_type;
385 res = r;
386 goto err;
387 }
388 }
389
390 dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date,
391 modification_date, read_date,
392 size, parameter);
393
394 if (dsp_parm == NULL) {
395 res = MAILIMF_ERROR_MEMORY;
396 goto free;
397 }
398
399 * result = dsp_parm;
400 * index = cur_token;
401
402 return MAILIMF_NO_ERROR;
403
404 free:
405 if (filename != NULL)
406 mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename);
407 if (creation_date != NULL)
408 mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date);
409 if (modification_date != NULL)
410 mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date);
411 if (read_date != NULL)
412 mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date);
413 if (parameter != NULL)
414 mailmime_parameter_free(dsp_parm->pa_data.pa_parameter);
415 err:
416 return res;
417}
418
419/*
420 filename-parm := "filename" "=" value
421*/
422
423static int
424mailmime_filename_parm_parse(const char * message, size_t length,
425 size_t * index, char ** result)
426{
427 char * value;
428 int r;
429 size_t cur_token;
430
431 cur_token = * index;
432
433 r = mailimf_token_case_insensitive_parse(message, length,
434 &cur_token, "filename");
435 if (r != MAILIMF_NO_ERROR)
436 return r;
437
438 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
439 if (r != MAILIMF_NO_ERROR)
440 return r;
441
442 r = mailmime_value_parse(message, length, &cur_token, &value);
443 if (r != MAILIMF_NO_ERROR)
444 return r;
445
446 * index = cur_token;
447 * result = value;
448
449 return MAILIMF_NO_ERROR;
450}
451
452/*
453 creation-date-parm := "creation-date" "=" quoted-date-time
454*/
455
456static int
457mailmime_creation_date_parm_parse(const char * message, size_t length,
458 size_t * index, char ** result)
459{
460 char * value;
461 int r;
462 size_t cur_token;
463
464 cur_token = * index;
465
466 r = mailimf_token_case_insensitive_parse(message, length,
467 &cur_token, "creation-date");
468 if (r != MAILIMF_NO_ERROR)
469 return r;
470
471 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474
475 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
476 if (r != MAILIMF_NO_ERROR)
477 return r;
478
479 * index = cur_token;
480 * result = value;
481
482 return MAILIMF_NO_ERROR;
483}
484
485/*
486 modification-date-parm := "modification-date" "=" quoted-date-time
487*/
488
489static int
490mailmime_modification_date_parm_parse(const char * message, size_t length,
491 size_t * index, char ** result)
492{
493 char * value;
494 size_t cur_token;
495 int r;
496
497 cur_token = * index;
498
499 r = mailimf_token_case_insensitive_parse(message, length,
500 &cur_token, "modification-date");
501 if (r != MAILIMF_NO_ERROR)
502 return r;
503
504 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
505 if (r != MAILIMF_NO_ERROR)
506 return r;
507
508 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
509 if (r != MAILIMF_NO_ERROR)
510 return r;
511
512 * index = cur_token;
513 * result = value;
514
515 return MAILIMF_NO_ERROR;
516}
517
518/*
519 read-date-parm := "read-date" "=" quoted-date-time
520*/
521
522static int
523mailmime_read_date_parm_parse(const char * message, size_t length,
524 size_t * index, char ** result)
525{
526 char * value;
527 size_t cur_token;
528 int r;
529
530 cur_token = * index;
531
532 r = mailimf_token_case_insensitive_parse(message, length,
533 &cur_token, "read-date");
534 if (r != MAILIMF_NO_ERROR)
535 return r;
536
537 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
538 if (r != MAILIMF_NO_ERROR)
539 return r;
540
541 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544
545 * index = cur_token;
546 * result = value;
547
548 return MAILIMF_NO_ERROR;
549}
550
551/*
552 size-parm := "size" "=" 1*DIGIT
553*/
554
555static int
556mailmime_size_parm_parse(const char * message, size_t length,
557 size_t * index, size_t * result)
558{
559 uint32_t value;
560 size_t cur_token;
561 int r;
562
563 cur_token = * index;
564
565 r = mailimf_token_case_insensitive_parse(message, length,
566 &cur_token, "size");
567 if (r != MAILIMF_NO_ERROR)
568 return r;
569
570 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
571 if (r != MAILIMF_NO_ERROR)
572 return r;
573
574 r = mailimf_number_parse(message, length, &cur_token, &value);
575 if (r != MAILIMF_NO_ERROR)
576 return r;
577
578 * index = cur_token;
579 * result = value;
580
581 return MAILIMF_NO_ERROR;
582}
583
584/*
585 quoted-date-time := quoted-string
586 ; contents MUST be an RFC 822 `date-time'
587 ; numeric timezones (+HHMM or -HHMM) MUST be used
588*/
589
590static int
591mailmime_quoted_date_time_parse(const char * message, size_t length,
592 size_t * index, char ** result)
593{
594 return mailimf_quoted_string_parse(message, length, index, result);
595}
diff --git a/libetpan/src/low-level/mime/mailmime_disposition.h b/libetpan/src/low-level/mime/mailmime_disposition.h
new file mode 100644
index 0000000..e992d7c
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_disposition.h
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_DISPOSITION_H
37
38#define MAILMIME_DISPOSITION_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_disposition_parse(const char * message, size_t length,
47 size_t * index,
48 struct mailmime_disposition ** result);
49
50int
51mailmime_disposition_type_parse(const char * message, size_t length,
52 size_t * index,
53 struct mailmime_disposition_type ** result);
54
55int mailmime_disposition_guess_type(const char * message, size_t length,
56 size_t index);
57
58#ifdef __cplusplus
59}
60#endif
61
62#endif
diff --git a/libetpan/src/low-level/mime/mailmime_types.c b/libetpan/src/low-level/mime/mailmime_types.c
new file mode 100644
index 0000000..115d17f
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types.c
@@ -0,0 +1,753 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_types.h"
37#include "mmapstring.h"
38
39#include <string.h>
40#include <stdlib.h>
41
42void mailmime_attribute_free(char * attribute)
43{
44 mailmime_token_free(attribute);
45}
46
47
48
49struct mailmime_composite_type *
50mailmime_composite_type_new(int ct_type, char * ct_token)
51{
52 struct mailmime_composite_type * ct;
53
54 ct = malloc(sizeof(* ct));
55 if (ct == NULL)
56 return NULL;
57
58 ct->ct_type = ct_type;
59 ct->ct_token = ct_token;
60
61 return ct;
62}
63
64void mailmime_composite_type_free(struct mailmime_composite_type * ct)
65{
66 if (ct->ct_token != NULL)
67 mailmime_extension_token_free(ct->ct_token);
68 free(ct);
69}
70
71
72struct mailmime_content *
73mailmime_content_new(struct mailmime_type * ct_type,
74 char * ct_subtype,
75 clist * ct_parameters)
76{
77 struct mailmime_content * content;
78
79 content = malloc(sizeof(* content));
80 if (content == NULL)
81 return NULL;
82
83 content->ct_type = ct_type;
84 content->ct_subtype = ct_subtype;
85 content->ct_parameters = ct_parameters;
86
87 return content;
88}
89
90void mailmime_content_free(struct mailmime_content * content)
91{
92 mailmime_type_free(content->ct_type);
93 mailmime_subtype_free(content->ct_subtype);
94 if (content->ct_parameters != NULL) {
95 clist_foreach(content->ct_parameters,
96 (clist_func) mailmime_parameter_free, NULL);
97 clist_free(content->ct_parameters);
98 }
99
100 free(content);
101}
102
103
104void mailmime_description_free(char * description)
105{
106 free(description);
107}
108
109struct mailmime_discrete_type *
110mailmime_discrete_type_new(int dt_type, char * dt_extension)
111{
112 struct mailmime_discrete_type * discrete_type;
113
114 discrete_type = malloc(sizeof(* discrete_type));
115 if (discrete_type == NULL)
116 return NULL;
117
118 discrete_type->dt_type = dt_type;
119 discrete_type->dt_extension = dt_extension;
120
121 return discrete_type;
122}
123
124void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type)
125{
126 if (discrete_type->dt_extension != NULL)
127 mailmime_extension_token_free(discrete_type->dt_extension);
128 free(discrete_type);
129}
130
131void mailmime_encoding_free(struct mailmime_mechanism * encoding)
132{
133 mailmime_mechanism_free(encoding);
134}
135
136void mailmime_extension_token_free(char * extension)
137{
138 mailmime_token_free(extension);
139}
140
141void mailmime_id_free(char * id)
142{
143 mailimf_msg_id_free(id);
144}
145
146struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token)
147{
148 struct mailmime_mechanism * mechanism;
149
150 mechanism = malloc(sizeof(* mechanism));
151 if (mechanism == NULL)
152 return NULL;
153
154 mechanism->enc_type = enc_type;
155 mechanism->enc_token = enc_token;
156
157 return mechanism;
158}
159
160void mailmime_mechanism_free(struct mailmime_mechanism * mechanism)
161{
162 if (mechanism->enc_token != NULL)
163 mailmime_token_free(mechanism->enc_token);
164 free(mechanism);
165}
166
167struct mailmime_parameter *
168mailmime_parameter_new(char * pa_name, char * pa_value)
169{
170 struct mailmime_parameter * parameter;
171
172 parameter = malloc(sizeof(* parameter));
173 if (parameter == NULL)
174 return NULL;
175
176 parameter->pa_name = pa_name;
177 parameter->pa_value = pa_value;
178
179 return parameter;
180}
181
182void mailmime_parameter_free(struct mailmime_parameter * parameter)
183{
184 mailmime_attribute_free(parameter->pa_name);
185 mailmime_value_free(parameter->pa_value);
186 free(parameter);
187}
188
189
190void mailmime_subtype_free(char * subtype)
191{
192 mailmime_extension_token_free(subtype);
193}
194
195
196void mailmime_token_free(char * token)
197{
198 free(token);
199}
200
201
202struct mailmime_type *
203mailmime_type_new(int tp_type,
204 struct mailmime_discrete_type * tp_discrete_type,
205 struct mailmime_composite_type * tp_composite_type)
206{
207 struct mailmime_type * mime_type;
208
209 mime_type = malloc(sizeof(* mime_type));
210 if (mime_type == NULL)
211 return NULL;
212
213 mime_type->tp_type = tp_type;
214 switch (tp_type) {
215 case MAILMIME_TYPE_DISCRETE_TYPE:
216 mime_type->tp_data.tp_discrete_type = tp_discrete_type;
217 break;
218 case MAILMIME_TYPE_COMPOSITE_TYPE:
219 mime_type->tp_data.tp_composite_type = tp_composite_type;
220 break;
221 }
222
223 return mime_type;
224}
225
226void mailmime_type_free(struct mailmime_type * type)
227{
228 switch (type->tp_type) {
229 case MAILMIME_TYPE_DISCRETE_TYPE:
230 mailmime_discrete_type_free(type->tp_data.tp_discrete_type);
231 break;
232 case MAILMIME_TYPE_COMPOSITE_TYPE:
233 mailmime_composite_type_free(type->tp_data.tp_composite_type);
234 break;
235 }
236 free(type);
237}
238
239void mailmime_value_free(char * value)
240{
241 free(value);
242}
243
244
245/*
246void mailmime_x_token_free(gchar * x_token)
247{
248 g_free(x_token);
249}
250*/
251
252struct mailmime_field *
253mailmime_field_new(int fld_type,
254 struct mailmime_content * fld_content,
255 struct mailmime_mechanism * fld_encoding,
256 char * fld_id,
257 char * fld_description,
258 uint32_t fld_version,
259 struct mailmime_disposition * fld_disposition,
260 struct mailmime_language * fld_language)
261{
262 struct mailmime_field * field;
263
264 field = malloc(sizeof(* field));
265 if (field == NULL)
266 return NULL;
267 field->fld_type = fld_type;
268
269 switch (fld_type) {
270 case MAILMIME_FIELD_TYPE:
271 field->fld_data.fld_content = fld_content;
272 break;
273 case MAILMIME_FIELD_TRANSFER_ENCODING:
274 field->fld_data.fld_encoding = fld_encoding;
275 break;
276 case MAILMIME_FIELD_ID:
277 field->fld_data.fld_id = fld_id;
278 break;
279 case MAILMIME_FIELD_DESCRIPTION:
280 field->fld_data.fld_description = fld_description;
281 break;
282 case MAILMIME_FIELD_VERSION:
283 field->fld_data.fld_version = fld_version;
284 break;
285 case MAILMIME_FIELD_DISPOSITION:
286 field->fld_data.fld_disposition = fld_disposition;
287 break;
288 case MAILMIME_FIELD_LANGUAGE:
289 field->fld_data.fld_language = fld_language;
290 break;
291 }
292 return field;
293}
294
295void mailmime_field_free(struct mailmime_field * field)
296{
297 switch (field->fld_type) {
298 case MAILMIME_FIELD_TYPE:
299 if (field->fld_data.fld_content != NULL)
300 mailmime_content_free(field->fld_data.fld_content);
301 break;
302 case MAILMIME_FIELD_TRANSFER_ENCODING:
303 if (field->fld_data.fld_encoding != NULL)
304 mailmime_encoding_free(field->fld_data.fld_encoding);
305 break;
306 case MAILMIME_FIELD_ID:
307 if (field->fld_data.fld_id != NULL)
308 mailmime_id_free(field->fld_data.fld_id);
309 break;
310 case MAILMIME_FIELD_DESCRIPTION:
311 if (field->fld_data.fld_description != NULL)
312 mailmime_description_free(field->fld_data.fld_description);
313 break;
314 case MAILMIME_FIELD_DISPOSITION:
315 if (field->fld_data.fld_disposition != NULL)
316 mailmime_disposition_free(field->fld_data.fld_disposition);
317 break;
318 case MAILMIME_FIELD_LANGUAGE:
319 if (field->fld_data.fld_language != NULL)
320 mailmime_language_free(field->fld_data.fld_language);
321 break;
322 }
323
324 free(field);
325}
326
327struct mailmime_fields * mailmime_fields_new(clist * fld_list)
328{
329 struct mailmime_fields * fields;
330
331 fields = malloc(sizeof(* fields));
332 if (fields == NULL)
333 return NULL;
334
335 fields->fld_list = fld_list;
336
337 return fields;
338}
339
340void mailmime_fields_free(struct mailmime_fields * fields)
341{
342 clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL);
343 clist_free(fields->fld_list);
344 free(fields);
345}
346
347
348/*
349struct mailmime_body_part *
350mailmime_body_part_new(gchar * text, guint32 size)
351{
352 struct mailmime_body_part * body_part;
353
354 body_part = g_new(struct mailmime_body_part, 1);
355 if (body_part == NULL)
356 return NULL;
357
358 body_part->text = text;
359 body_part->size = size;
360
361 return body_part;
362}
363
364void mailmime_body_part_free(struct mailmime_body_part * body_part)
365{
366 g_free(body_part);
367}
368*/
369
370struct mailmime_multipart_body *
371mailmime_multipart_body_new(clist * bd_list)
372{
373 struct mailmime_multipart_body * mp_body;
374
375 mp_body = malloc(sizeof(* mp_body));
376 if (mp_body == NULL)
377 return NULL;
378
379 mp_body->bd_list = bd_list;
380
381 return mp_body;
382}
383
384void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body)
385{
386 clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL);
387 clist_free(mp_body->bd_list);
388 free(mp_body);
389}
390
391
392
393
394struct mailmime * mailmime_new(int mm_type,
395 const char * mm_mime_start, size_t mm_length,
396 struct mailmime_fields * mm_mime_fields,
397 struct mailmime_content * mm_content_type,
398 struct mailmime_data * mm_body,
399 struct mailmime_data * mm_preamble,
400 struct mailmime_data * mm_epilogue,
401 clist * mm_mp_list,
402 struct mailimf_fields * mm_fields,
403 struct mailmime * mm_msg_mime)
404{
405 struct mailmime * mime;
406 clistiter * cur;
407
408 mime = malloc(sizeof(* mime));
409 if (mime == NULL)
410 return NULL;
411
412 mime->mm_parent = NULL;
413 mime->mm_parent_type = MAILMIME_NONE;
414 mime->mm_multipart_pos = NULL;
415
416 mime->mm_type = mm_type;
417 mime->mm_mime_start = mm_mime_start;
418 mime->mm_length = mm_length;
419 mime->mm_mime_fields = mm_mime_fields;
420 mime->mm_content_type = mm_content_type;
421
422 mime->mm_body = mm_body;
423
424 switch (mm_type) {
425 case MAILMIME_SINGLE:
426 mime->mm_data.mm_single = mm_body;
427 break;
428
429 case MAILMIME_MULTIPLE:
430 mime->mm_data.mm_multipart.mm_preamble = mm_preamble;
431 mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue;
432 mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list;
433
434 for(cur = clist_begin(mm_mp_list) ; cur != NULL ;
435 cur = clist_next(cur)) {
436 struct mailmime * submime;
437
438 submime = clist_content(cur);
439 submime->mm_parent = mime;
440 submime->mm_parent_type = MAILMIME_MULTIPLE;
441 submime->mm_multipart_pos = cur;
442 }
443 break;
444
445 case MAILMIME_MESSAGE:
446 mime->mm_data.mm_message.mm_fields = mm_fields;
447 mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime;
448 if (mm_msg_mime != NULL) {
449 mm_msg_mime->mm_parent = mime;
450 mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE;
451 }
452 break;
453
454 }
455
456 return mime;
457}
458
459void mailmime_free(struct mailmime * mime)
460{
461 switch (mime->mm_type) {
462 case MAILMIME_SINGLE:
463 if ((mime->mm_body == NULL) && (mime->mm_data.mm_single != NULL))
464 mailmime_data_free(mime->mm_data.mm_single);
465 /* do nothing */
466 break;
467
468 case MAILMIME_MULTIPLE:
469 if (mime->mm_data.mm_multipart.mm_preamble != NULL)
470 mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble);
471 if (mime->mm_data.mm_multipart.mm_epilogue != NULL)
472 mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue);
473 clist_foreach(mime->mm_data.mm_multipart.mm_mp_list,
474 (clist_func) mailmime_free, NULL);
475 clist_free(mime->mm_data.mm_multipart.mm_mp_list);
476 break;
477
478 case MAILMIME_MESSAGE:
479 if (mime->mm_data.mm_message.mm_fields != NULL)
480 mailimf_fields_free(mime->mm_data.mm_message.mm_fields);
481 if (mime->mm_data.mm_message.mm_msg_mime != NULL)
482 mailmime_free(mime->mm_data.mm_message.mm_msg_mime);
483 break;
484
485 }
486 if (mime->mm_body != NULL)
487 mailmime_data_free(mime->mm_body);
488
489 if (mime->mm_mime_fields != NULL)
490 mailmime_fields_free(mime->mm_mime_fields);
491 if (mime->mm_content_type != NULL)
492 mailmime_content_free(mime->mm_content_type);
493 free(mime);
494}
495
496
497
498struct mailmime_encoded_word *
499mailmime_encoded_word_new(char * wd_charset, char * wd_text)
500{
501 struct mailmime_encoded_word * ew;
502
503 ew = malloc(sizeof(* ew));
504 if (ew == NULL)
505 return NULL;
506 ew->wd_charset = wd_charset;
507 ew->wd_text = wd_text;
508
509 return ew;
510}
511
512void mailmime_charset_free(char * charset)
513{
514 free(charset);
515}
516
517void mailmime_encoded_text_free(char * text)
518{
519 free(text);
520}
521
522void mailmime_encoded_word_free(struct mailmime_encoded_word * ew)
523{
524 mailmime_charset_free(ew->wd_charset);
525 mailmime_encoded_text_free(ew->wd_text);
526 free(ew);
527}
528
529
530
531/* mailmime_disposition */
532
533
534struct mailmime_disposition *
535mailmime_disposition_new(struct mailmime_disposition_type * dsp_type,
536 clist * dsp_parms)
537{
538 struct mailmime_disposition * dsp;
539
540 dsp = malloc(sizeof(* dsp));
541 if (dsp == NULL)
542 return NULL;
543 dsp->dsp_type = dsp_type;
544 dsp->dsp_parms = dsp_parms;
545
546 return dsp;
547}
548
549void mailmime_disposition_free(struct mailmime_disposition * dsp)
550{
551 mailmime_disposition_type_free(dsp->dsp_type);
552 clist_foreach(dsp->dsp_parms,
553 (clist_func) mailmime_disposition_parm_free, NULL);
554 clist_free(dsp->dsp_parms);
555 free(dsp);
556}
557
558
559
560struct mailmime_disposition_type *
561mailmime_disposition_type_new(int dsp_type, char * dsp_extension)
562{
563 struct mailmime_disposition_type * m_dsp_type;
564
565 m_dsp_type = malloc(sizeof(* m_dsp_type));
566 if (m_dsp_type == NULL)
567 return NULL;
568
569 m_dsp_type->dsp_type = dsp_type;
570 m_dsp_type->dsp_extension = dsp_extension;
571
572 return m_dsp_type;
573}
574
575void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type)
576{
577 if (dsp_type->dsp_extension != NULL)
578 free(dsp_type->dsp_extension);
579 free(dsp_type);
580}
581
582
583struct mailmime_disposition_parm *
584mailmime_disposition_parm_new(int pa_type,
585 char * pa_filename,
586 char * pa_creation_date,
587 char * pa_modification_date,
588 char * pa_read_date,
589 size_t pa_size,
590 struct mailmime_parameter * pa_parameter)
591{
592 struct mailmime_disposition_parm * dsp_parm;
593
594 dsp_parm = malloc(sizeof(* dsp_parm));
595 if (dsp_parm == NULL)
596 return NULL;
597
598 dsp_parm->pa_type = pa_type;
599 switch (pa_type) {
600 case MAILMIME_DISPOSITION_PARM_FILENAME:
601 dsp_parm->pa_data.pa_filename = pa_filename;
602 break;
603 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
604 dsp_parm->pa_data.pa_creation_date = pa_creation_date;
605 break;
606 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
607 dsp_parm->pa_data.pa_modification_date = pa_modification_date;
608 break;
609 case MAILMIME_DISPOSITION_PARM_READ_DATE:
610 dsp_parm->pa_data.pa_read_date = pa_read_date;
611 break;
612 case MAILMIME_DISPOSITION_PARM_SIZE:
613 dsp_parm->pa_data.pa_size = pa_size;
614 break;
615 case MAILMIME_DISPOSITION_PARM_PARAMETER:
616 dsp_parm->pa_data.pa_parameter = pa_parameter;
617 break;
618 }
619
620 return dsp_parm;
621}
622
623void mailmime_disposition_parm_free(struct mailmime_disposition_parm *
624 dsp_parm)
625{
626 switch (dsp_parm->pa_type) {
627 case MAILMIME_DISPOSITION_PARM_FILENAME:
628 mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename);
629 break;
630 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
631 mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date);
632 break;
633 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
634 mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date);
635 break;
636 case MAILMIME_DISPOSITION_PARM_READ_DATE:
637 mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date);
638 break;
639 case MAILMIME_DISPOSITION_PARM_PARAMETER:
640 mailmime_parameter_free(dsp_parm->pa_data.pa_parameter);
641 break;
642 }
643
644 free(dsp_parm);
645}
646
647
648void mailmime_filename_parm_free(char * filename)
649{
650 mailmime_value_free(filename);
651}
652
653void mailmime_creation_date_parm_free(char * date)
654{
655 mailmime_quoted_date_time_free(date);
656}
657
658void mailmime_modification_date_parm_free(char * date)
659{
660 mailmime_quoted_date_time_free(date);
661}
662
663void mailmime_read_date_parm_free(char * date)
664{
665 mailmime_quoted_date_time_free(date);
666}
667
668void mailmime_quoted_date_time_free(char * date)
669{
670 mailimf_quoted_string_free(date);
671}
672
673struct mailmime_section * mailmime_section_new(clist * sec_list)
674{
675 struct mailmime_section * section;
676
677 section = malloc(sizeof(* section));
678 if (section == NULL)
679 return NULL;
680
681 section->sec_list = sec_list;
682
683 return section;
684}
685
686void mailmime_section_free(struct mailmime_section * section)
687{
688 clist_foreach(section->sec_list, (clist_func) free, NULL);
689 clist_free(section->sec_list);
690 free(section);
691}
692
693
694
695struct mailmime_language * mailmime_language_new(clist * lg_list)
696{
697 struct mailmime_language * lang;
698
699 lang = malloc(sizeof(* lang));
700 if (lang == NULL)
701 return NULL;
702
703 lang->lg_list = lg_list;
704
705 return lang;
706}
707
708void mailmime_language_free(struct mailmime_language * lang)
709{
710 clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL);
711 clist_free(lang->lg_list);
712 free(lang);
713}
714
715void mailmime_decoded_part_free(char * part)
716{
717 mmap_string_unref(part);
718}
719
720struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding,
721 int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename)
722{
723 struct mailmime_data * mime_data;
724
725 mime_data = malloc(sizeof(* mime_data));
726 if (mime_data == NULL)
727 return NULL;
728
729 mime_data->dt_type = dt_type;
730 mime_data->dt_encoding = dt_encoding;
731 mime_data->dt_encoded = dt_encoded;
732 switch (dt_type) {
733 case MAILMIME_DATA_TEXT:
734 mime_data->dt_data.dt_text.dt_data = dt_data;
735 mime_data->dt_data.dt_text.dt_length = dt_length;
736 break;
737 case MAILMIME_DATA_FILE:
738 mime_data->dt_data.dt_filename = dt_filename;
739 break;
740 }
741
742 return mime_data;
743}
744
745void mailmime_data_free(struct mailmime_data * mime_data)
746{
747 switch (mime_data->dt_type) {
748 case MAILMIME_DATA_FILE:
749 free(mime_data->dt_data.dt_filename);
750 break;
751 }
752 free(mime_data);
753}
diff --git a/libetpan/src/low-level/mime/mailmime_types.h b/libetpan/src/low-level/mime/mailmime_types.h
new file mode 100644
index 0000000..21f0d96
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types.h
@@ -0,0 +1,440 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_TYPES_H
37
38#define MAILMIME_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <libetpan/mailimf.h>
46#include <libetpan/clist.h>
47
48enum {
49 MAILMIME_COMPOSITE_TYPE_ERROR,
50 MAILMIME_COMPOSITE_TYPE_MESSAGE,
51 MAILMIME_COMPOSITE_TYPE_MULTIPART,
52 MAILMIME_COMPOSITE_TYPE_EXTENSION
53};
54
55struct mailmime_composite_type {
56 int ct_type;
57 char * ct_token;
58};
59
60
61struct mailmime_content {
62 struct mailmime_type * ct_type;
63 char * ct_subtype;
64 clist * ct_parameters; /* elements are (struct mailmime_parameter *) */
65};
66
67
68enum {
69 MAILMIME_DISCRETE_TYPE_ERROR,
70 MAILMIME_DISCRETE_TYPE_TEXT,
71 MAILMIME_DISCRETE_TYPE_IMAGE,
72 MAILMIME_DISCRETE_TYPE_AUDIO,
73 MAILMIME_DISCRETE_TYPE_VIDEO,
74 MAILMIME_DISCRETE_TYPE_APPLICATION,
75 MAILMIME_DISCRETE_TYPE_EXTENSION
76};
77
78struct mailmime_discrete_type {
79 int dt_type;
80 char * dt_extension;
81};
82
83enum {
84 MAILMIME_FIELD_NONE,
85 MAILMIME_FIELD_TYPE,
86 MAILMIME_FIELD_TRANSFER_ENCODING,
87 MAILMIME_FIELD_ID,
88 MAILMIME_FIELD_DESCRIPTION,
89 MAILMIME_FIELD_VERSION,
90 MAILMIME_FIELD_DISPOSITION,
91 MAILMIME_FIELD_LANGUAGE,
92};
93
94struct mailmime_field {
95 int fld_type;
96 union {
97 struct mailmime_content * fld_content;
98 struct mailmime_mechanism * fld_encoding;
99 char * fld_id;
100 char * fld_description;
101 uint32_t fld_version;
102 struct mailmime_disposition * fld_disposition;
103 struct mailmime_language * fld_language;
104 } fld_data;
105};
106
107enum {
108 MAILMIME_MECHANISM_ERROR,
109 MAILMIME_MECHANISM_7BIT,
110 MAILMIME_MECHANISM_8BIT,
111 MAILMIME_MECHANISM_BINARY,
112 MAILMIME_MECHANISM_QUOTED_PRINTABLE,
113 MAILMIME_MECHANISM_BASE64,
114 MAILMIME_MECHANISM_TOKEN
115};
116
117struct mailmime_mechanism {
118 int enc_type;
119 char * enc_token;
120};
121
122
123struct mailmime_fields {
124 clist * fld_list; /* list of (struct mailmime_field *) */
125};
126
127
128struct mailmime_parameter {
129 char * pa_name;
130 char * pa_value;
131};
132
133enum {
134 MAILMIME_TYPE_ERROR,
135 MAILMIME_TYPE_DISCRETE_TYPE,
136 MAILMIME_TYPE_COMPOSITE_TYPE
137};
138
139struct mailmime_type {
140 int tp_type;
141 union {
142 struct mailmime_discrete_type * tp_discrete_type;
143 struct mailmime_composite_type * tp_composite_type;
144 } tp_data;
145};
146
147void mailmime_attribute_free(char * attribute);
148
149struct mailmime_composite_type *
150mailmime_composite_type_new(int ct_type, char * ct_token);
151
152void mailmime_composite_type_free(struct mailmime_composite_type * ct);
153
154struct mailmime_content *
155mailmime_content_new(struct mailmime_type * ct_type,
156 char * ct_subtype,
157 clist * ct_parameters);
158
159void mailmime_content_free(struct mailmime_content * content);
160
161void mailmime_description_free(char * description);
162
163struct mailmime_discrete_type *
164mailmime_discrete_type_new(int dt_type, char * dt_extension);
165
166void mailmime_discrete_type_free(struct mailmime_discrete_type *
167 discrete_type);
168
169void mailmime_encoding_free(struct mailmime_mechanism * encoding);
170
171void mailmime_extension_token_free(char * extension);
172
173void mailmime_id_free(char * id);
174
175struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token);
176
177void mailmime_mechanism_free(struct mailmime_mechanism * mechanism);
178
179struct mailmime_parameter *
180mailmime_parameter_new(char * pa_name, char * pa_value);
181
182void mailmime_parameter_free(struct mailmime_parameter * parameter);
183
184void mailmime_subtype_free(char * subtype);
185
186void mailmime_token_free(char * token);
187
188struct mailmime_type *
189mailmime_type_new(int tp_type,
190 struct mailmime_discrete_type * tp_discrete_type,
191 struct mailmime_composite_type * tp_composite_type);
192
193void mailmime_type_free(struct mailmime_type * type);
194
195void mailmime_value_free(char * value);
196
197
198
199struct mailmime_language {
200 clist * lg_list; /* atom (char *) */
201};
202
203struct mailmime_language * mailmime_language_new(clist * lg_list);
204
205void mailmime_language_free(struct mailmime_language * lang);
206
207
208/*
209void mailmime_x_token_free(gchar * x_token);
210*/
211
212struct mailmime_field *
213mailmime_field_new(int fld_type,
214 struct mailmime_content * fld_content,
215 struct mailmime_mechanism * fld_encoding,
216 char * fld_id,
217 char * fld_description,
218 uint32_t fld_version,
219 struct mailmime_disposition * fld_disposition,
220 struct mailmime_language * fld_language);
221
222void mailmime_field_free(struct mailmime_field * field);
223
224struct mailmime_fields * mailmime_fields_new(clist * fld_list);
225
226void mailmime_fields_free(struct mailmime_fields * fields);
227
228
229struct mailmime_multipart_body {
230 clist * bd_list;
231};
232
233struct mailmime_multipart_body *
234mailmime_multipart_body_new(clist * bd_list);
235
236void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body);
237
238
239enum {
240 MAILMIME_DATA_TEXT,
241 MAILMIME_DATA_FILE,
242};
243
244struct mailmime_data {
245 int dt_type;
246 int dt_encoding;
247 int dt_encoded;
248 union {
249 struct {
250 const char * dt_data;
251 size_t dt_length;
252 } dt_text;
253 char * dt_filename;
254 } dt_data;
255};
256
257struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding,
258 int dt_encoded, const char * dt_data, size_t dt_length,
259 char * dt_filename);
260
261void mailmime_data_free(struct mailmime_data * mime_data);
262
263
264enum {
265 MAILMIME_NONE,
266 MAILMIME_SINGLE,
267 MAILMIME_MULTIPLE,
268 MAILMIME_MESSAGE,
269};
270
271struct mailmime {
272 /* parent information */
273 int mm_parent_type;
274 struct mailmime * mm_parent;
275 clistiter * mm_multipart_pos;
276
277 int mm_type;
278 const char * mm_mime_start;
279 size_t mm_length;
280
281 struct mailmime_fields * mm_mime_fields;
282 struct mailmime_content * mm_content_type;
283
284 struct mailmime_data * mm_body;
285 union {
286 /* single part */
287 struct mailmime_data * mm_single; /* XXX - was body */
288
289 /* multi-part */
290 struct {
291 struct mailmime_data * mm_preamble;
292 struct mailmime_data * mm_epilogue;
293 clist * mm_mp_list;
294 } mm_multipart;
295
296 /* message */
297 struct {
298 struct mailimf_fields * mm_fields;
299 struct mailmime * mm_msg_mime;
300 } mm_message;
301
302 } mm_data;
303};
304
305struct mailmime * mailmime_new(int mm_type,
306 const char * mm_mime_start, size_t mm_length,
307 struct mailmime_fields * mm_mime_fields,
308 struct mailmime_content * mm_content_type,
309 struct mailmime_data * mm_body,
310 struct mailmime_data * mm_preamble,
311 struct mailmime_data * mm_epilogue,
312 clist * mm_mp_list,
313 struct mailimf_fields * mm_fields,
314 struct mailmime * mm_msg_mime);
315
316void mailmime_free(struct mailmime * mime);
317
318struct mailmime_encoded_word {
319 char * wd_charset;
320 char * wd_text;
321};
322
323struct mailmime_encoded_word *
324mailmime_encoded_word_new(char * wd_charset, char * wd_text);
325
326void mailmime_encoded_word_free(struct mailmime_encoded_word * ew);
327
328void mailmime_charset_free(char * charset);
329
330void mailmime_encoded_text_free(char * text);
331
332
333struct mailmime_disposition {
334 struct mailmime_disposition_type * dsp_type;
335 clist * dsp_parms; /* struct mailmime_disposition_parm */
336};
337
338
339enum {
340 MAILMIME_DISPOSITION_TYPE_ERROR,
341 MAILMIME_DISPOSITION_TYPE_INLINE,
342 MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
343 MAILMIME_DISPOSITION_TYPE_EXTENSION
344};
345
346struct mailmime_disposition_type {
347 int dsp_type;
348 char * dsp_extension;
349};
350
351
352enum {
353 MAILMIME_DISPOSITION_PARM_FILENAME,
354 MAILMIME_DISPOSITION_PARM_CREATION_DATE,
355 MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE,
356 MAILMIME_DISPOSITION_PARM_READ_DATE,
357 MAILMIME_DISPOSITION_PARM_SIZE,
358 MAILMIME_DISPOSITION_PARM_PARAMETER
359};
360
361struct mailmime_disposition_parm {
362 int pa_type;
363 union {
364 char * pa_filename;
365 char * pa_creation_date;
366 char * pa_modification_date;
367 char * pa_read_date;
368 size_t pa_size;
369 struct mailmime_parameter * pa_parameter;
370 } pa_data;
371};
372
373struct mailmime_disposition *
374mailmime_disposition_new(struct mailmime_disposition_type * dsp_type,
375 clist * dsp_parms);
376
377void mailmime_disposition_free(struct mailmime_disposition * dsp);
378
379struct mailmime_disposition_type *
380mailmime_disposition_type_new(int dt_type, char * dt_extension);
381
382void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type);
383
384struct mailmime_disposition_parm *
385mailmime_disposition_parm_new(int pa_type,
386 char * pa_filename,
387 char * pa_creation_date,
388 char * pa_modification_date,
389 char * pa_read_date,
390 size_t pa_size,
391 struct mailmime_parameter * pa_parameter);
392
393void mailmime_disposition_parm_free(struct mailmime_disposition_parm *
394 dsp_parm);
395
396void mailmime_filename_parm_free(char * filename);
397
398void mailmime_creation_date_parm_free(char * date);
399
400void mailmime_modification_date_parm_free(char * date);
401
402void mailmime_read_date_parm_free(char * date);
403
404void mailmime_quoted_date_time_free(char * date);
405
406struct mailmime_section {
407 clist * sec_list; /* list of (uint32 *) */
408};
409
410struct mailmime_section * mailmime_section_new(clist * list);
411
412void mailmime_section_free(struct mailmime_section * section);
413
414
415void mailmime_decoded_part_free(char * part);
416
417struct mailmime_single_fields {
418 struct mailmime_content * fld_content;
419 char * fld_content_charset;
420 char * fld_content_boundary;
421 char * fld_content_name;
422 struct mailmime_mechanism * fld_encoding;
423 char * fld_id;
424 char * fld_description;
425 uint32_t fld_version;
426 struct mailmime_disposition * fld_disposition;
427 char * fld_disposition_filename;
428 char * fld_disposition_creation_date;
429 char * fld_disposition_modification_date;
430 char * fld_disposition_read_date;
431 size_t fld_disposition_size;
432 struct mailmime_language * fld_language;
433};
434
435#ifdef __cplusplus
436}
437#endif
438
439#endif
440
diff --git a/libetpan/src/low-level/mime/mailmime_types_helper.c b/libetpan/src/low-level/mime/mailmime_types_helper.c
new file mode 100644
index 0000000..e45330c
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types_helper.c
@@ -0,0 +1,1385 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_types_helper.h"
37#include "clist.h"
38
39#include "mailmime.h"
40
41#include <string.h>
42#include <time.h>
43#include <sys/types.h>
44#include <unistd.h>
45#include <stdlib.h>
46
47#define MIME_VERSION (1 << 16)
48
49int mailmime_transfer_encoding_get(struct mailmime_fields * fields)
50{
51 clistiter * cur;
52
53 for(cur = clist_begin(fields->fld_list) ;
54 cur != NULL ; cur = clist_next(cur)) {
55 struct mailmime_field * field;
56
57 field = clist_content(cur);
58 if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING)
59 return field->fld_data.fld_encoding->enc_type;
60 }
61
62 return MAILMIME_MECHANISM_8BIT;
63}
64
65struct mailmime_disposition *
66mailmime_disposition_new_filename(int type, char * filename)
67{
68 return mailmime_disposition_new_with_data(type, filename,
69 NULL, NULL, NULL, (size_t) -1);
70
71}
72
73struct mailmime_fields * mailmime_fields_new_empty(void)
74{
75 clist * list;
76 struct mailmime_fields * fields;
77
78 list = clist_new();
79 if (list == NULL)
80 goto err;
81
82 fields = mailmime_fields_new(list);
83 if (fields == NULL)
84 goto free;
85
86 return fields;
87
88 free:
89 clist_free(list);
90 err:
91 return NULL;
92}
93
94int mailmime_fields_add(struct mailmime_fields * fields,
95 struct mailmime_field * field)
96{
97 int r;
98
99 r = clist_append(fields->fld_list, field);
100 if (r < 0)
101 return MAILIMF_ERROR_MEMORY;
102
103 return MAILIMF_NO_ERROR;
104}
105
106static void mailmime_field_detach(struct mailmime_field * field)
107{
108 switch (field->fld_type) {
109 case MAILMIME_FIELD_TYPE:
110 field->fld_data.fld_content = NULL;
111 break;
112 case MAILMIME_FIELD_TRANSFER_ENCODING:
113 field->fld_data.fld_encoding = NULL;
114 break;
115 case MAILMIME_FIELD_ID:
116 field->fld_data.fld_id = NULL;
117 break;
118 case MAILMIME_FIELD_DESCRIPTION:
119 field->fld_data.fld_description = NULL;
120 break;
121 case MAILMIME_FIELD_DISPOSITION:
122 field->fld_data.fld_disposition = NULL;
123 break;
124 case MAILMIME_FIELD_LANGUAGE:
125 field->fld_data.fld_language = NULL;
126 break;
127 }
128}
129
130struct mailmime_fields *
131mailmime_fields_new_with_data(struct mailmime_mechanism * encoding,
132 char * id,
133 char * description,
134 struct mailmime_disposition * disposition,
135 struct mailmime_language * language)
136{
137 struct mailmime_field * field;
138 struct mailmime_fields * fields;
139 int r;
140
141 fields = mailmime_fields_new_empty();
142 if (fields == NULL)
143 goto err;
144
145#if 0
146 if (content != NULL) {
147 field = mailmime_field_new(MAILMIME_FIELD_TYPE,
148 content, NULL, NULL, NULL, 0, NULL, NULL);
149 if (field == NULL)
150 goto free;
151
152 r = mailmime_fields_add(fields, field);
153 if (r != MAILIMF_NO_ERROR) {
154 mailmime_field_detach(field);
155 mailmime_field_free(field);
156 goto free;
157 }
158 }
159#endif
160
161 if (encoding != NULL) {
162 field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING,
163 NULL, encoding, NULL, NULL, 0, NULL, NULL);
164 if (field == NULL)
165 goto free;
166
167 r = mailmime_fields_add(fields, field);
168 if (r != MAILIMF_NO_ERROR) {
169 mailmime_field_detach(field);
170 mailmime_field_free(field);
171 goto free;
172 }
173 }
174
175 if (id != NULL) {
176 field = mailmime_field_new(MAILMIME_FIELD_ID,
177 NULL, NULL, id, NULL, 0, NULL, NULL);
178 if (field == NULL)
179 goto free;
180
181 r = mailmime_fields_add(fields, field);
182 if (r != MAILIMF_NO_ERROR) {
183 mailmime_field_detach(field);
184 mailmime_field_free(field);
185 goto free;
186 }
187 }
188
189 if (description != NULL) {
190 field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION,
191 NULL, NULL, NULL, description, 0, NULL, NULL);
192 if (field == NULL)
193 goto free;
194
195 r = mailmime_fields_add(fields, field);
196 if (r != MAILIMF_NO_ERROR) {
197 mailmime_field_detach(field);
198 mailmime_field_free(field);
199 goto free;
200 }
201 }
202
203 if (disposition != NULL) {
204 field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION,
205 NULL, NULL, NULL, NULL, 0, disposition, NULL);
206 if (field == NULL)
207 goto free;
208
209 r = mailmime_fields_add(fields, field);
210 if (r != MAILIMF_NO_ERROR) {
211 mailmime_field_detach(field);
212 mailmime_field_free(field);
213 goto free;
214 }
215 }
216
217 if (language != NULL) {
218 field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION,
219 NULL, NULL, NULL, NULL, 0, NULL, language);
220 if (field == NULL)
221 goto free;
222
223 r = mailmime_fields_add(fields, field);
224 if (r != MAILIMF_NO_ERROR) {
225 mailmime_field_detach(field);
226 mailmime_field_free(field);
227 goto free;
228 }
229 }
230
231 return fields;
232
233 free:
234 clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL);
235 mailmime_fields_free(fields);
236 err:
237 return NULL;
238}
239
240struct mailmime_fields *
241mailmime_fields_new_with_version(struct mailmime_mechanism * encoding,
242 char * id,
243 char * description,
244 struct mailmime_disposition * disposition,
245 struct mailmime_language * language)
246{
247 struct mailmime_field * field;
248 struct mailmime_fields * fields;
249 int r;
250
251 fields = mailmime_fields_new_with_data(encoding, id, description,
252 disposition, language);
253 if (fields == NULL)
254 goto err;
255
256 field = mailmime_field_new(MAILMIME_FIELD_VERSION,
257 NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL);
258 if (field == NULL)
259 goto free;
260
261 r = mailmime_fields_add(fields, field);
262 if (r != MAILIMF_NO_ERROR) {
263 mailmime_field_detach(field);
264 mailmime_field_free(field);
265 goto free;
266 }
267
268 return fields;
269
270 free:
271 clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL);
272 mailmime_fields_free(fields);
273 err:
274 return NULL;
275}
276
277
278struct mailmime_content * mailmime_get_content_message(void)
279{
280 clist * list;
281 struct mailmime_composite_type * composite_type;
282 struct mailmime_type * mime_type;
283 struct mailmime_content * content;
284 char * subtype;
285
286 composite_type =
287 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE,
288 NULL);
289 if (composite_type == NULL)
290 goto err;
291
292 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
293 NULL, composite_type);
294 if (mime_type == NULL)
295 goto free_composite;
296 composite_type = NULL;
297
298 list = clist_new();
299 if (list == NULL)
300 goto free_mime_type;
301
302 subtype = strdup("rfc822");
303 if (subtype == NULL)
304 goto free_list;
305
306 content = mailmime_content_new(mime_type, subtype, list);
307 if (content == NULL)
308 goto free_subtype;
309
310 return content;
311
312 free_subtype:
313 free(subtype);
314 free_list:
315 clist_free(list);
316 free_mime_type:
317 mailmime_type_free(mime_type);
318 free_composite:
319 if (composite_type != NULL)
320 mailmime_composite_type_free(composite_type);
321 err:
322 return NULL;
323}
324
325struct mailmime_content * mailmime_get_content_text(void)
326{
327 clist * list;
328 struct mailmime_discrete_type * discrete_type;
329 struct mailmime_type * mime_type;
330 struct mailmime_content * content;
331 char * subtype;
332
333 discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
334 NULL);
335 if (discrete_type == NULL)
336 goto err;
337
338 mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE,
339 discrete_type, NULL);
340 if (mime_type == NULL)
341 goto free_discrete;
342 discrete_type = NULL;
343
344 list = clist_new();
345 if (list == NULL)
346 goto free_type;
347
348 subtype = strdup("plain");
349 if (subtype == NULL)
350 goto free_list;
351
352 content = mailmime_content_new(mime_type, subtype, list);
353 if (content == NULL)
354 goto free_subtype;
355
356 return content;
357
358 free_subtype:
359 free(subtype);
360 free_list:
361 clist_free(list);
362 free_type:
363 mailmime_type_free(mime_type);
364 free_discrete:
365 if (discrete_type != NULL)
366 mailmime_discrete_type_free(discrete_type);
367 err:
368 return NULL;
369}
370
371
372
373
374
375
376
377
378/* mailmime build */
379
380
381#if 0
382struct mailmime *
383mailmime_new_message_file(char * filename)
384{
385 struct mailmime_content * content;
386 struct mailmime * build_info;
387 struct mailmime_data * msg_content;
388 struct mailmime_fields * mime_fields;
389
390 content = mailmime_get_content_message();
391 if (content == NULL) {
392 goto err;
393 }
394
395 mime_fields = mailmime_fields_new_with_version(NULL, NULL,
396 NULL, NULL, NULL);
397 if (mime_fields == NULL)
398 goto free_content;
399
400 msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT,
401 1, NULL, 0, filename);
402 if (msg_content == NULL)
403 goto free_fields;
404
405 build_info = mailmime_new(MAILMIME_MESSAGE,
406 NULL, 0, mime_fields, content,
407 msg_content, NULL, NULL, NULL, NULL, NULL);
408 if (build_info == NULL)
409 goto free_msg_content;
410
411 return build_info;
412
413 free_msg_content:
414 mailmime_data_free(msg_content);
415 free_fields:
416 mailmime_fields_free(mime_fields);
417 free_content:
418 mailmime_content_free(content);
419 err:
420 return NULL;
421}
422
423struct mailmime *
424mailmime_new_message_text(char * data_str, size_t length)
425{
426 struct mailmime_content * content;
427 struct mailmime * build_info;
428 struct mailmime_data * msg_content;
429 struct mailmime_fields * mime_fields;
430
431 content = mailmime_get_content_message();
432 if (content == NULL) {
433 goto err;
434 }
435
436 mime_fields = mailmime_fields_new_with_version(NULL, NULL,
437 NULL, NULL, NULL);
438 if (mime_fields == NULL)
439 goto free_fields;
440
441 msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT,
442 1, data_str, length, NULL);
443 if (msg_content == NULL)
444 goto free_content;
445
446 build_info = mailmime_new(MAILMIME_MESSAGE,
447 NULL, 0, mime_fields, content,
448 msg_content, NULL, NULL, NULL,
449 NULL, NULL);
450 if (build_info == NULL)
451 goto free_msg_content;
452
453 return build_info;
454
455 free_msg_content:
456 mailmime_data_free(msg_content);
457 free_fields:
458 mailmime_fields_free(mime_fields);
459 free_content:
460 mailmime_content_free(content);
461 err:
462 return NULL;
463}
464#endif
465
466struct mailmime *
467mailmime_new_message_data(struct mailmime * msg_mime)
468{
469 struct mailmime_content * content;
470 struct mailmime * build_info;
471 struct mailmime_fields * mime_fields;
472
473 content = mailmime_get_content_message();
474 if (content == NULL)
475 goto err;
476
477 mime_fields = mailmime_fields_new_with_version(NULL, NULL,
478 NULL, NULL, NULL);
479 if (mime_fields == NULL)
480 goto free_content;
481
482 build_info = mailmime_new(MAILMIME_MESSAGE,
483 NULL, 0, mime_fields, content,
484 NULL, NULL, NULL, NULL,
485 NULL, msg_mime);
486 if (build_info == NULL)
487 goto free_fields;
488
489 return build_info;
490
491 free_fields:
492 mailmime_fields_free(mime_fields);
493 free_content:
494 mailmime_content_free(content);
495 err:
496 return NULL;
497}
498
499#define MAX_MESSAGE_ID 512
500
501static char * generate_boundary()
502{
503 char id[MAX_MESSAGE_ID];
504 time_t now;
505 char name[MAX_MESSAGE_ID];
506 long value;
507
508 now = time(NULL);
509 value = random();
510
511 gethostname(name, MAX_MESSAGE_ID);
512 snprintf(id, MAX_MESSAGE_ID, "%lx_%lx_%x", now, value, getpid());
513
514 return strdup(id);
515}
516
517struct mailmime *
518mailmime_new_empty(struct mailmime_content * content,
519 struct mailmime_fields * mime_fields)
520{
521 struct mailmime * build_info;
522 clist * list;
523 int r;
524 int mime_type;
525
526 list = NULL;
527
528 switch (content->ct_type->tp_type) {
529 case MAILMIME_TYPE_DISCRETE_TYPE:
530 mime_type = MAILMIME_SINGLE;
531 break;
532
533 case MAILMIME_TYPE_COMPOSITE_TYPE:
534 switch (content->ct_type->tp_data.tp_composite_type->ct_type) {
535 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
536 mime_type = MAILMIME_MULTIPLE;
537 break;
538
539 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
540 if (strcasecmp(content->ct_subtype, "rfc822") == 0)
541 mime_type = MAILMIME_MESSAGE;
542 else
543 mime_type = MAILMIME_SINGLE;
544 break;
545
546 default:
547 goto err;
548 }
549 break;
550
551 default:
552 goto err;
553 }
554
555 if (mime_type == MAILMIME_MULTIPLE) {
556 char * attr_name;
557 char * attr_value;
558 struct mailmime_parameter * param;
559 clist * parameters;
560 char * boundary;
561
562 list = clist_new();
563 if (list == NULL)
564 goto err;
565
566 attr_name = strdup("boundary");
567 if (attr_name == NULL)
568 goto free_list;
569
570 boundary = generate_boundary();
571 attr_value = boundary;
572 if (attr_name == NULL) {
573 free(attr_name);
574 goto free_list;
575 }
576
577 param = mailmime_parameter_new(attr_name, attr_value);
578 if (param == NULL) {
579 free(attr_value);
580 free(attr_name);
581 goto free_list;
582 }
583
584 if (content->ct_parameters == NULL) {
585 parameters = clist_new();
586 if (parameters == NULL) {
587 mailmime_parameter_free(param);
588 goto free_list;
589 }
590 }
591 else
592 parameters = content->ct_parameters;
593
594 r = clist_append(parameters, param);
595 if (r != 0) {
596 clist_free(parameters);
597 mailmime_parameter_free(param);
598 goto free_list;
599 }
600
601 if (content->ct_parameters == NULL)
602 content->ct_parameters = parameters;
603 }
604
605 build_info = mailmime_new(mime_type,
606 NULL, 0, mime_fields, content,
607 NULL, NULL, NULL, list,
608 NULL, NULL);
609 if (build_info == NULL) {
610 clist_free(list);
611 return NULL;
612 }
613
614 return build_info;
615
616 free_list:
617 clist_free(list);
618 err:
619 return NULL;
620}
621
622
623int
624mailmime_new_with_content(const char * content_type,
625 struct mailmime_fields * mime_fields,
626 struct mailmime ** result)
627{
628 int r;
629 size_t cur_token;
630 struct mailmime_content * content;
631 struct mailmime * build_info;
632#if 0
633 int mime_type;
634#endif
635 int res;
636
637 cur_token = 0;
638 r = mailmime_content_parse(content_type, strlen(content_type),
639 &cur_token,
640 &content);
641 if (r != MAILIMF_NO_ERROR) {
642 res = r;
643 goto err;
644 }
645
646#if 0
647 switch (content->type->type) {
648 case MAILMIME_TYPE_DISCRETE_TYPE:
649 mime_type = MAILMIME_SINGLE;
650 break;
651
652 case MAILMIME_TYPE_COMPOSITE_TYPE:
653 switch (content->type->composite_type->type) {
654 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
655 mime_type = MAILMIME_MULTIPLE;
656 break;
657
658 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
659 if (strcasecmp(content->subtype, "rfc822") == 0)
660 mime_type = MAILMIME_MESSAGE;
661 else
662 mime_type = MAILMIME_SINGLE;
663 break;
664
665 default:
666 res = MAILIMF_ERROR_INVAL;
667 goto free;
668 }
669 break;
670
671 default:
672 res = MAILIMF_ERROR_INVAL;
673 goto free;
674 }
675#endif
676
677 build_info = mailmime_new_empty(content, mime_fields);
678 if (build_info == NULL) {
679 res = MAILIMF_ERROR_MEMORY;
680 goto free;
681 }
682
683 * result = build_info;
684
685 return MAILIMF_NO_ERROR;
686
687 free:
688 mailmime_content_free(content);
689 err:
690 return res;
691}
692
693int mailmime_set_preamble_file(struct mailmime * build_info,
694 char * filename)
695{
696 struct mailmime_data * data;
697
698 data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT,
699 0, NULL, 0, filename);
700 if (data == NULL)
701 return MAILIMF_ERROR_MEMORY;
702
703 build_info->mm_data.mm_multipart.mm_preamble = data;
704
705 return MAILIMF_NO_ERROR;
706}
707
708int mailmime_set_epilogue_file(struct mailmime * build_info,
709 char * filename)
710{
711 struct mailmime_data * data;
712
713 data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT,
714 0, NULL, 0, filename);
715 if (data == NULL)
716 return MAILIMF_ERROR_MEMORY;
717
718 build_info->mm_data.mm_multipart.mm_epilogue = data;
719
720 return MAILIMF_NO_ERROR;
721}
722
723int mailmime_set_preamble_text(struct mailmime * build_info,
724 char * data_str, size_t length)
725{
726 struct mailmime_data * data;
727
728 data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT,
729 0, data_str, length, NULL);
730 if (data == NULL)
731 return MAILIMF_ERROR_MEMORY;
732
733 build_info->mm_data.mm_multipart.mm_preamble = data;
734
735 return MAILIMF_NO_ERROR;
736}
737
738int mailmime_set_epilogue_text(struct mailmime * build_info,
739 char * data_str, size_t length)
740{
741 struct mailmime_data * data;
742
743 data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT,
744 0, data_str, length, NULL);
745 if (data == NULL)
746 return MAILIMF_ERROR_MEMORY;
747
748 build_info->mm_data.mm_multipart.mm_epilogue = data;
749
750 return MAILIMF_NO_ERROR;
751}
752
753
754int mailmime_set_body_file(struct mailmime * build_info,
755 char * filename)
756{
757 int encoding;
758 struct mailmime_data * data;
759
760 encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields);
761
762 data = mailmime_data_new(MAILMIME_DATA_FILE, encoding,
763 0, NULL, 0, filename);
764 if (data == NULL)
765 return MAILIMF_ERROR_MEMORY;
766
767 build_info->mm_data.mm_single = data;
768
769 return MAILIMF_NO_ERROR;
770}
771
772int mailmime_set_body_text(struct mailmime * build_info,
773 char * data_str, size_t length)
774{
775 int encoding;
776 struct mailmime_data * data;
777
778 encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields);
779
780 data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding,
781 0, data_str, length, NULL);
782 if (data == NULL)
783 return MAILIMF_ERROR_MEMORY;
784
785 build_info->mm_data.mm_single = data;
786
787 return MAILIMF_NO_ERROR;
788}
789
790
791/* add a part as subpart of a mime part */
792
793int mailmime_add_part(struct mailmime * build_info,
794 struct mailmime * part)
795{
796 int r;
797
798 if (build_info->mm_type == MAILMIME_MESSAGE) {
799 build_info->mm_data.mm_message.mm_msg_mime = part;
800 part->mm_parent_type = MAILMIME_MESSAGE;
801 part->mm_parent = build_info;
802 }
803 else if (build_info->mm_type == MAILMIME_MULTIPLE) {
804 r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part);
805 if (r != 0)
806 return MAILIMF_ERROR_MEMORY;
807
808 part->mm_parent_type = MAILMIME_MULTIPLE;
809 part->mm_parent = build_info;
810 part->mm_multipart_pos =
811 clist_end(build_info->mm_data.mm_multipart.mm_mp_list);
812 }
813 else {
814 return MAILIMF_ERROR_INVAL;
815 }
816 return MAILIMF_NO_ERROR;
817}
818
819/* detach part from parent */
820
821void mailmime_remove_part(struct mailmime * mime)
822{
823 struct mailmime * parent;
824
825 parent = mime->mm_parent;
826 if (parent == NULL)
827 return;
828
829 switch (mime->mm_parent_type) {
830 case MAILMIME_MESSAGE:
831 mime->mm_parent = NULL;
832 parent->mm_data.mm_message.mm_msg_mime = NULL;
833 break;
834
835 case MAILMIME_MULTIPLE:
836 mime->mm_parent = NULL;
837 clist_delete(parent->mm_data.mm_multipart.mm_mp_list,
838 mime->mm_multipart_pos);
839 break;
840 }
841}
842
843
844/*
845 attach a part to a mime part and create multipart/mixed
846 when needed, when the parent part has already some part
847 attached to it.
848*/
849
850int mailmime_smart_add_part(struct mailmime * mime,
851 struct mailmime * mime_sub)
852{
853 struct mailmime * saved_sub;
854 struct mailmime * mp;
855 int res;
856 int r;
857
858 switch (mime->mm_type) {
859 case MAILMIME_SINGLE:
860 res = MAILIMF_ERROR_INVAL;
861 goto err;
862
863 case MAILMIME_MULTIPLE:
864 r = mailmime_add_part(mime, mime_sub);
865 if (r != MAILIMF_NO_ERROR) {
866 res = MAILIMF_ERROR_MEMORY;
867 goto err;
868 }
869
870 return MAILIMF_NO_ERROR;
871 }
872
873 /* MAILMIME_MESSAGE */
874
875 if (mime->mm_data.mm_message.mm_msg_mime == NULL) {
876 /* there is no subpart, we can simply attach it */
877
878 r = mailmime_add_part(mime, mime_sub);
879 if (r != MAILIMF_NO_ERROR) {
880 res = MAILIMF_ERROR_MEMORY;
881 goto err;
882 }
883
884 return MAILIMF_NO_ERROR;
885 }
886
887 if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) {
888 /* in case the subpart is multipart, simply attach it to the subpart */
889
890 return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub);
891 }
892
893 /* we save the current subpart, ... */
894
895 saved_sub = mime->mm_data.mm_message.mm_msg_mime;
896
897 /* create a multipart */
898
899 mp = mailmime_multiple_new("multipart/mixed");
900 if (mp == NULL) {
901 res = MAILIMF_ERROR_MEMORY;
902 goto err;
903 }
904
905 /* detach the saved subpart from the parent */
906
907 mailmime_remove_part(saved_sub);
908
909 /* the created multipart is the new child of the parent */
910
911 r = mailmime_add_part(mime, mp);
912 if (r != MAILIMF_NO_ERROR) {
913 res = MAILIMF_ERROR_MEMORY;
914 goto free_mp;
915 }
916
917 /* then, attach the saved subpart and ... */
918
919 r = mailmime_add_part(mp, saved_sub);
920 if (r != MAILIMF_NO_ERROR) {
921 res = MAILIMF_ERROR_MEMORY;
922 goto free_saved_sub;
923 }
924
925 /* the given part to the parent */
926
927 r = mailmime_add_part(mp, mime_sub);
928 if (r != MAILIMF_NO_ERROR) {
929 res = MAILIMF_ERROR_MEMORY;
930 goto free_saved_sub;
931 }
932
933 return MAILIMF_NO_ERROR;
934
935 free_mp:
936 mailmime_free(mp);
937 free_saved_sub:
938 mailmime_free(saved_sub);
939 err:
940 return res;
941}
942
943
944
945/* detach part from parent and free it only if the part has no child */
946
947int mailmime_smart_remove_part(struct mailmime * mime)
948{
949 struct mailmime * parent;
950 int res;
951
952 parent = mime->mm_parent;
953 if (parent == NULL) {
954 res = MAILIMF_ERROR_INVAL;
955 goto err;
956 }
957
958 switch (mime->mm_type) {
959 case MAILMIME_MESSAGE:
960 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
961 res = MAILIMF_ERROR_INVAL;
962 goto err;
963 }
964
965 mailmime_remove_part(mime);
966
967 mailmime_free(mime);
968
969 return MAILIMF_NO_ERROR;
970
971 case MAILMIME_MULTIPLE:
972 if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) {
973 res = MAILIMF_ERROR_INVAL;
974 goto err;
975 }
976
977 mailmime_remove_part(mime);
978
979 mailmime_free(mime);
980
981 return MAILIMF_NO_ERROR;
982
983 case MAILMIME_SINGLE:
984 mailmime_remove_part(mime);
985
986 mailmime_free(mime);
987
988 return MAILIMF_NO_ERROR;
989
990 default:
991 return MAILIMF_ERROR_INVAL;
992 }
993
994 err:
995 return res;
996}
997
998
999/* create a mailmime_content structure (Content-Type field) */
1000
1001struct mailmime_content * mailmime_content_new_with_str(const char * str)
1002{
1003 int r;
1004 size_t cur_token;
1005 struct mailmime_content * content;
1006
1007 cur_token = 0;
1008 r = mailmime_content_parse(str, strlen(str), &cur_token, &content);
1009 if (r != MAILIMF_NO_ERROR)
1010 return NULL;
1011
1012 return content;
1013}
1014
1015/* create MIME fields with only the field Content-Transfer-Encoding */
1016
1017struct mailmime_fields * mailmime_fields_new_encoding(int type)
1018{
1019 struct mailmime_mechanism * encoding;
1020 struct mailmime_fields * mime_fields;
1021
1022 encoding = mailmime_mechanism_new(type, NULL);
1023 if (encoding == NULL)
1024 goto err;
1025
1026 mime_fields = mailmime_fields_new_with_data(encoding,
1027 NULL, NULL, NULL, NULL);
1028 if (mime_fields == NULL)
1029 goto free;
1030
1031 return mime_fields;
1032
1033 free:
1034 mailmime_mechanism_free(encoding);
1035 err:
1036 return NULL;
1037}
1038
1039
1040/* create a multipart MIME part */
1041
1042struct mailmime * mailmime_multiple_new(const char * type)
1043{
1044 struct mailmime_fields * mime_fields;
1045 struct mailmime_content * content;
1046 struct mailmime * mp;
1047
1048 mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT);
1049 if (mime_fields == NULL)
1050 goto err;
1051
1052 content = mailmime_content_new_with_str(type);
1053 if (content == NULL)
1054 goto free_fields;
1055
1056 mp = mailmime_new_empty(content, mime_fields);
1057 if (mp == NULL)
1058 goto free_content;
1059
1060 return mp;
1061
1062 free_content:
1063 mailmime_content_free(content);
1064 free_fields:
1065 mailmime_fields_free(mime_fields);
1066 err:
1067 return NULL;
1068}
1069
1070
1071
1072void mailmime_set_imf_fields(struct mailmime * build_info,
1073 struct mailimf_fields * mm_fields)
1074{
1075 build_info->mm_data.mm_message.mm_fields = mm_fields;
1076}
1077
1078#if 0
1079struct mailmime_content * mailmime_get_content(char * mime_type)
1080{
1081 struct mailmime_content *content;
1082 int r;
1083 size_t cur_token;
1084
1085 cur_token = 0;
1086 r = mailmime_content_parse(mime_type, strlen(mime_type),
1087 &cur_token, &content);
1088 if (r != MAILIMF_NO_ERROR)
1089 return NULL;
1090
1091 return content;
1092}
1093#endif
1094
1095
1096
1097
1098struct mailmime_disposition *
1099mailmime_disposition_new_with_data(int type,
1100 char * filename, char * creation_date, char * modification_date,
1101 char * read_date, size_t size)
1102{
1103 struct mailmime_disposition_type * dsp_type;
1104 clist * list;
1105 int r;
1106 struct mailmime_disposition_parm * parm;
1107 struct mailmime_disposition * dsp;
1108
1109 dsp_type = mailmime_disposition_type_new(type, NULL);
1110 if (dsp_type == NULL)
1111 goto err;
1112
1113 list = clist_new();
1114 if (list == NULL)
1115 goto free_dsp_type;
1116
1117 if (filename != NULL) {
1118 parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME,
1119 filename, NULL, NULL, NULL, 0, NULL);
1120 if (parm == NULL)
1121 goto free_list;
1122
1123 r = clist_append(list, parm);
1124 if (r < 0) {
1125 mailmime_disposition_parm_free(parm);
1126 goto free_list;
1127 }
1128 }
1129
1130 if (creation_date != NULL) {
1131 parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE,
1132 NULL, creation_date, NULL, NULL, 0, NULL);
1133 if (parm == NULL)
1134 goto free_list;
1135
1136 r = clist_append(list, parm);
1137 if (r < 0) {
1138 mailmime_disposition_parm_free(parm);
1139 goto free_list;
1140 }
1141 }
1142
1143 if (modification_date != NULL) {
1144 parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE,
1145 NULL, NULL, modification_date, NULL, 0, NULL);
1146 if (parm == NULL)
1147 goto free_list;
1148
1149 r = clist_append(list, parm);
1150 if (r < 0) {
1151 mailmime_disposition_parm_free(parm);
1152 goto free_list;
1153 }
1154 }
1155
1156 if (read_date != NULL) {
1157 parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE,
1158 NULL, NULL, NULL, read_date, 0, NULL);
1159 if (parm == NULL)
1160 goto free_list;
1161
1162 r = clist_append(list, parm);
1163 if (r < 0) {
1164 mailmime_disposition_parm_free(parm);
1165 goto free_list;
1166 }
1167 }
1168
1169 if (size != (size_t) -1) {
1170 parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE,
1171 NULL, NULL, NULL, NULL, size, NULL);
1172 if (parm == NULL)
1173 goto free_list;
1174
1175 r = clist_append(list, parm);
1176 if (r < 0) {
1177 mailmime_disposition_parm_free(parm);
1178 goto free_list;
1179 }
1180 }
1181
1182 dsp = mailmime_disposition_new(dsp_type, list);
1183
1184 return dsp;
1185
1186 free_list:
1187 clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL);
1188 clist_free(list);
1189 free_dsp_type:
1190 mailmime_disposition_type_free(dsp_type);
1191 err:
1192 return NULL;
1193}
1194
1195
1196static void mailmime_disposition_single_fields_init(struct
1197 mailmime_single_fields * single_fields,
1198 struct mailmime_disposition * fld_disposition)
1199{
1200 clistiter * cur;
1201
1202 single_fields->fld_disposition = fld_disposition;
1203
1204 for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ;
1205 cur = clist_next(cur)) {
1206 struct mailmime_disposition_parm * param;
1207
1208 param = clist_content(cur);
1209
1210 switch (param->pa_type) {
1211 case MAILMIME_DISPOSITION_PARM_FILENAME:
1212 single_fields->fld_disposition_filename = param->pa_data.pa_filename;
1213 break;
1214
1215 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
1216 single_fields->fld_disposition_creation_date =
1217 param->pa_data.pa_creation_date;
1218 break;
1219
1220 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
1221 single_fields->fld_disposition_modification_date =
1222 param->pa_data.pa_modification_date;
1223 break;
1224
1225 case MAILMIME_DISPOSITION_PARM_READ_DATE:
1226 single_fields->fld_disposition_read_date =
1227 param->pa_data.pa_read_date;
1228 break;
1229
1230 case MAILMIME_DISPOSITION_PARM_SIZE:
1231 single_fields->fld_disposition_size = param->pa_data.pa_size;
1232 break;
1233 }
1234 }
1235}
1236
1237static void mailmime_content_single_fields_init(struct
1238 mailmime_single_fields * single_fields,
1239 struct mailmime_content * fld_content)
1240{
1241 clistiter * cur;
1242
1243 single_fields->fld_content = fld_content;
1244
1245 for(cur = clist_begin(fld_content->ct_parameters) ;
1246 cur != NULL ; cur = clist_next(cur)) {
1247 struct mailmime_parameter * param;
1248
1249 param = clist_content(cur);
1250
1251 if (strcasecmp(param->pa_name, "boundary") == 0)
1252 single_fields->fld_content_boundary = param->pa_value;
1253
1254 if (strcasecmp(param->pa_name, "charset") == 0)
1255 single_fields->fld_content_charset = param->pa_value;
1256
1257 if (strcasecmp(param->pa_name, "name") == 0)
1258 single_fields->fld_content_name = param->pa_value;
1259 }
1260}
1261
1262void mailmime_single_fields_init(struct mailmime_single_fields * single_fields,
1263 struct mailmime_fields * fld_fields,
1264 struct mailmime_content * fld_content)
1265{
1266 clistiter * cur;
1267
1268 memset(single_fields, 0, sizeof(struct mailmime_single_fields));
1269
1270 if (fld_content != NULL)
1271 mailmime_content_single_fields_init(single_fields, fld_content);
1272
1273 if (fld_fields == NULL)
1274 return;
1275
1276 for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ;
1277 cur = clist_next(cur)) {
1278 struct mailmime_field * field;
1279
1280 field = clist_content(cur);
1281
1282 switch (field->fld_type) {
1283 case MAILMIME_FIELD_TYPE:
1284 mailmime_content_single_fields_init(single_fields,
1285 field->fld_data.fld_content);
1286 break;
1287
1288 case MAILMIME_FIELD_TRANSFER_ENCODING:
1289 single_fields->fld_encoding = field->fld_data.fld_encoding;
1290 break;
1291
1292 case MAILMIME_FIELD_ID:
1293 single_fields->fld_id = field->fld_data.fld_id;
1294 break;
1295
1296 case MAILMIME_FIELD_DESCRIPTION:
1297 single_fields->fld_description = field->fld_data.fld_description;
1298 break;
1299
1300 case MAILMIME_FIELD_VERSION:
1301 single_fields->fld_version = field->fld_data.fld_version;
1302 break;
1303
1304 case MAILMIME_FIELD_DISPOSITION:
1305 mailmime_disposition_single_fields_init(single_fields,
1306 field->fld_data.fld_disposition);
1307 break;
1308
1309 case MAILMIME_FIELD_LANGUAGE:
1310 single_fields->fld_language = field->fld_data.fld_language;
1311 break;
1312 }
1313 }
1314}
1315
1316struct mailmime_single_fields *
1317mailmime_single_fields_new(struct mailmime_fields * fld_fields,
1318 struct mailmime_content * fld_content)
1319{
1320 struct mailmime_single_fields * single_fields;
1321
1322 single_fields = malloc(sizeof(struct mailmime_single_fields));
1323 if (single_fields == NULL)
1324 goto err;
1325
1326 mailmime_single_fields_init(single_fields, fld_fields, fld_content);
1327
1328 return single_fields;
1329
1330 err:
1331 return NULL;
1332}
1333
1334
1335void mailmime_single_fields_free(struct mailmime_single_fields *
1336 single_fields)
1337{
1338 free(single_fields);
1339}
1340
1341struct mailmime_fields * mailmime_fields_new_filename(int dsp_type,
1342 char * filename, int encoding_type)
1343{
1344 struct mailmime_disposition * dsp;
1345 struct mailmime_mechanism * encoding;
1346 struct mailmime_fields * mime_fields;
1347
1348 dsp = mailmime_disposition_new_with_data(dsp_type,
1349 filename, NULL, NULL, NULL, (size_t) -1);
1350 if (dsp == NULL)
1351 goto err;
1352
1353 encoding = mailmime_mechanism_new(encoding_type, NULL);
1354 if (encoding == NULL)
1355 goto free_dsp;
1356
1357 mime_fields = mailmime_fields_new_with_data(encoding,
1358 NULL, NULL, dsp, NULL);
1359 if (mime_fields == NULL)
1360 goto free_encoding;
1361
1362 return mime_fields;
1363
1364 free_encoding:
1365 mailmime_encoding_free(encoding);
1366 free_dsp:
1367 mailmime_disposition_free(dsp);
1368 err:
1369 return NULL;
1370}
1371
1372struct mailmime_data *
1373mailmime_data_new_data(int encoding, int encoded,
1374 const char * data, size_t length)
1375{
1376 return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL);
1377}
1378
1379struct mailmime_data *
1380mailmime_data_new_file(int encoding, int encoded,
1381 char * filename)
1382{
1383 return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename);
1384}
1385
diff --git a/libetpan/src/low-level/mime/mailmime_types_helper.h b/libetpan/src/low-level/mime/mailmime_types_helper.h
new file mode 100644
index 0000000..cdbbff9
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types_helper.h
@@ -0,0 +1,165 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_TYPES_HELPER_H
37
38#define MAILMIME_TYPES_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_transfer_encoding_get(struct mailmime_fields * fields);
47
48struct mailmime_disposition *
49mailmime_disposition_new_filename(int type, char * filename);
50
51struct mailmime_fields * mailmime_fields_new_empty(void);
52
53int mailmime_fields_add(struct mailmime_fields * fields,
54 struct mailmime_field * field);
55
56struct mailmime_fields *
57mailmime_fields_new_with_data(struct mailmime_mechanism * encoding,
58 char * id,
59 char * description,
60 struct mailmime_disposition * disposition,
61 struct mailmime_language * language);
62
63struct mailmime_fields *
64mailmime_fields_new_with_version(struct mailmime_mechanism * encoding,
65 char * id,
66 char * description,
67 struct mailmime_disposition * disposition,
68 struct mailmime_language * language);
69
70struct mailmime_content * mailmime_get_content_message(void);
71struct mailmime_content * mailmime_get_content_text(void);
72/* struct mailmime_content * mailmime_get_content(char * mime_type); */
73
74#define mailmime_get_content mailmime_content_new_with_str
75
76struct mailmime_data *
77mailmime_data_new_data(int encoding, int encoded,
78 const char * data, size_t length);
79
80struct mailmime_data *
81mailmime_data_new_file(int encoding, int encoded,
82 char * filename);
83
84#if 0
85struct mailmime *
86mailmime_new_message_file(char * filename);
87
88struct mailmime *
89mailmime_new_message_text(char * data_str, size_t length);
90#endif
91
92struct mailmime *
93mailmime_new_message_data(struct mailmime * msg_mime);
94
95struct mailmime *
96mailmime_new_empty(struct mailmime_content * content,
97 struct mailmime_fields * mime_fields);
98
99int
100mailmime_new_with_content(const char * content_type,
101 struct mailmime_fields * mime_fields,
102 struct mailmime ** result);
103
104int mailmime_set_preamble_file(struct mailmime * build_info,
105 char * filename);
106
107int mailmime_set_epilogue_file(struct mailmime * build_info,
108 char * filename);
109
110int mailmime_set_preamble_text(struct mailmime * build_info,
111 char * data_str, size_t length);
112
113int mailmime_set_epilogue_text(struct mailmime * build_info,
114 char * data_str, size_t length);
115
116int mailmime_set_body_file(struct mailmime * build_info,
117 char * filename);
118
119int mailmime_set_body_text(struct mailmime * build_info,
120 char * data_str, size_t length);
121
122int mailmime_add_part(struct mailmime * build_info,
123 struct mailmime * part);
124
125void mailmime_remove_part(struct mailmime * mime);
126
127void mailmime_set_imf_fields(struct mailmime * build_info,
128 struct mailimf_fields * fields);
129
130
131struct mailmime_disposition *
132mailmime_disposition_new_with_data(int type,
133 char * filename, char * creation_date, char * modification_date,
134 char * read_date, size_t size);
135
136void mailmime_single_fields_init(struct mailmime_single_fields * single_fields,
137 struct mailmime_fields * fld_fields,
138 struct mailmime_content * fld_content);
139
140struct mailmime_single_fields *
141mailmime_single_fields_new(struct mailmime_fields * fld_fields,
142 struct mailmime_content * fld_content);
143
144void mailmime_single_fields_free(struct mailmime_single_fields *
145 single_fields);
146
147int mailmime_smart_add_part(struct mailmime * mime,
148 struct mailmime * mime_sub);
149
150int mailmime_smart_remove_part(struct mailmime * mime);
151
152struct mailmime_content * mailmime_content_new_with_str(const char * str);
153
154struct mailmime_fields * mailmime_fields_new_encoding(int type);
155
156struct mailmime * mailmime_multiple_new(const char * type);
157
158struct mailmime_fields * mailmime_fields_new_filename(int dsp_type,
159 char * filename, int encoding_type);
160
161#ifdef __cplusplus
162}
163#endif
164
165#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write.c b/libetpan/src/low-level/mime/mailmime_write.c
new file mode 100644
index 0000000..4bce0d5
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write.c
@@ -0,0 +1,1416 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_write.h"
37
38#include <stdlib.h>
39#include <string.h>
40#include <time.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46
47#include "mailimf_write.h"
48#include "mailmime_content.h"
49#include "mailmime_types_helper.h"
50
51#define MAX_MAIL_COL 78
52
53#ifndef TRUE
54#define TRUE 1
55#endif
56
57#ifndef FALSE
58#define FALSE 0
59#endif
60
61static int mailmime_field_write(FILE * f, int * col,
62 struct mailmime_field * field);
63
64static int mailmime_id_write(FILE * f, int * col, char * id);
65
66static int mailmime_description_write(FILE * f, int * col, char * descr);
67
68static int mailmime_version_write(FILE * f, int * col, uint32_t version);
69
70static int mailmime_encoding_write(FILE * f, int * col,
71 struct mailmime_mechanism * encoding);
72
73static int mailmime_language_write(FILE * f, int * col,
74 struct mailmime_language * language);
75
76static int mailmime_disposition_write(FILE * f, int * col,
77 struct mailmime_disposition *
78 disposition);
79
80static int
81mailmime_disposition_param_write(FILE * f, int * col,
82 struct mailmime_disposition_parm * param);
83
84static int mailmime_parameter_write(FILE * f, int * col,
85 struct mailmime_parameter * param);
86
87/*
88static int mailmime_content_write(FILE * f, int * col,
89 struct mailmime_content * content);
90*/
91
92static int mailmime_type_write(FILE * f, int * col,
93 struct mailmime_type * type);
94
95static int
96mailmime_discrete_type_write(FILE * f, int * col,
97 struct mailmime_discrete_type * discrete_type);
98
99static int
100mailmime_composite_type_write(FILE * f, int * col,
101 struct mailmime_composite_type * composite_type);
102
103static int mailmime_sub_write(FILE * f, int * col,
104 struct mailmime * build_info);
105
106
107/* ***** */
108
109int mailmime_fields_write(FILE * f, int * col, struct mailmime_fields * fields)
110{
111 int r;
112 clistiter * cur;
113
114 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
115 cur = clist_next(cur)) {
116 struct mailmime_field * field;
117
118 field = cur->data;
119 r = mailmime_field_write(f, col, field);
120 if (r != MAILIMF_NO_ERROR)
121 return r;
122 }
123
124 return MAILIMF_NO_ERROR;
125}
126
127static int mailmime_field_write(FILE * f, int * col,
128 struct mailmime_field * field)
129{
130 int r;
131
132 switch (field->fld_type) {
133 case MAILMIME_FIELD_TYPE:
134 r = mailmime_content_write(f, col, field->fld_data.fld_content);
135 break;
136
137 case MAILMIME_FIELD_TRANSFER_ENCODING:
138 r = mailmime_encoding_write(f, col, field->fld_data.fld_encoding);
139 break;
140
141 case MAILMIME_FIELD_ID:
142 r = mailmime_id_write(f, col, field->fld_data.fld_id);
143 break;
144
145 case MAILMIME_FIELD_DESCRIPTION:
146 r = mailmime_description_write(f, col, field->fld_data.fld_description);
147 break;
148
149 case MAILMIME_FIELD_VERSION:
150 r = mailmime_version_write(f, col, field->fld_data.fld_version);
151 break;
152
153 case MAILMIME_FIELD_DISPOSITION:
154 r = mailmime_disposition_write(f, col, field->fld_data.fld_disposition);
155 break;
156
157 case MAILMIME_FIELD_LANGUAGE:
158 r = mailmime_language_write(f, col, field->fld_data.fld_language);
159 break;
160
161 default:
162 r = MAILIMF_ERROR_INVAL;
163 break;
164 }
165
166 if (r != MAILIMF_NO_ERROR)
167 return r;
168
169 return MAILIMF_NO_ERROR;
170}
171
172static int mailmime_id_write(FILE * f, int * col, char * id)
173{
174 int r;
175
176 r = mailimf_string_write(f, col, "Content-ID: ", 12);
177 if (r != MAILIMF_NO_ERROR)
178 return r;
179
180 r = mailimf_string_write(f, col, "<", 1);
181 if (r != MAILIMF_NO_ERROR)
182 return r;
183
184 r = mailimf_string_write(f, col, id, strlen(id));
185 if (r != MAILIMF_NO_ERROR)
186 return r;
187
188 r = mailimf_string_write(f, col, ">", 1);
189 if (r != MAILIMF_NO_ERROR)
190 return r;
191
192 r = mailimf_string_write(f, col, "\r\n", 2);
193 if (r != MAILIMF_NO_ERROR)
194 return r;
195#if 0
196 * col = 0;
197#endif
198
199 return MAILIMF_NO_ERROR;
200}
201
202static int mailmime_description_write(FILE * f, int * col, char * descr)
203{
204 int r;
205
206 r = mailimf_string_write(f, col, "Content-Description: ", 21);
207 if (r != MAILIMF_NO_ERROR)
208 return r;
209
210 r = mailimf_string_write(f, col, descr, strlen(descr));
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = mailimf_string_write(f, col, "\r\n", 2);
215 if (r != MAILIMF_NO_ERROR)
216 return r;
217#if 0
218 * col = 0;
219#endif
220
221 return MAILIMF_NO_ERROR;
222}
223
224static int mailmime_version_write(FILE * f, int * col, uint32_t version)
225{
226 int r;
227 char versionstr[40];
228
229 r = mailimf_string_write(f, col, "MIME-Version: ", 14);
230 if (r != MAILIMF_NO_ERROR)
231 return r;
232
233 snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF);
234
235 r = mailimf_string_write(f, col, versionstr, strlen(versionstr));
236 if (r != MAILIMF_NO_ERROR)
237 return r;
238
239 r = mailimf_string_write(f, col, "\r\n", 2);
240 if (r != MAILIMF_NO_ERROR)
241 return r;
242#if 0
243 * col = 0;
244#endif
245
246 return MAILIMF_NO_ERROR;
247}
248
249static int mailmime_encoding_write(FILE * f, int * col,
250 struct mailmime_mechanism * encoding)
251{
252 int r;
253
254 r = mailimf_string_write(f, col, "Content-Transfer-Encoding: ", 27);
255 if (r != MAILIMF_NO_ERROR)
256 return r;
257
258 switch (encoding->enc_type) {
259 case MAILMIME_MECHANISM_7BIT:
260 r = mailimf_string_write(f, col, "7bit", 4);
261 break;
262
263 case MAILMIME_MECHANISM_8BIT:
264 r = mailimf_string_write(f, col, "8bit", 4);
265 break;
266
267 case MAILMIME_MECHANISM_BINARY:
268 r = mailimf_string_write(f, col, "binary", 6);
269 break;
270
271 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
272 r = mailimf_string_write(f, col, "quoted-printable", 16);
273 break;
274
275 case MAILMIME_MECHANISM_BASE64:
276 r = mailimf_string_write(f, col, "base64", 6);
277 break;
278
279 case MAILMIME_MECHANISM_TOKEN:
280 r = mailimf_string_write(f, col, encoding->enc_token,
281 strlen(encoding->enc_token));
282 break;
283
284 default:
285 r = MAILIMF_ERROR_INVAL;
286 break;
287 }
288
289 if (r != MAILIMF_NO_ERROR)
290 return r;
291
292 r = mailimf_string_write(f, col, "\r\n", 2);
293 if (r != MAILIMF_NO_ERROR)
294 return r;
295#if 0
296 * col = 0;
297#endif
298
299 return MAILIMF_NO_ERROR;
300}
301
302static int mailmime_language_write(FILE * f, int * col,
303 struct mailmime_language * language)
304{
305 int r;
306 clistiter * cur;
307 int first;
308
309 r = mailimf_string_write(f, col, "Content-Language: ", 18);
310 if (r != MAILIMF_NO_ERROR)
311 return r;
312
313 first = TRUE;
314
315 for(cur = clist_begin(language->lg_list) ; cur != NULL ;
316 cur = clist_next(cur)) {
317 char * lang;
318 size_t len;
319
320 lang = clist_content(cur);
321 len = strlen(lang);
322
323 if (!first) {
324 r = mailimf_string_write(f, col, ", ", 2);
325 if (r != MAILIMF_NO_ERROR)
326 return r;
327 }
328 else {
329 first = FALSE;
330 }
331
332 if (* col > 1) {
333
334 if (* col + len > MAX_MAIL_COL) {
335 r = mailimf_string_write(f, col, "\r\n ", 3);
336 if (r != MAILIMF_NO_ERROR)
337 return r;
338#if 0
339 * col = 1;
340#endif
341 }
342 }
343
344 r = mailimf_string_write(f, col, lang, len);
345 if (r != MAILIMF_NO_ERROR)
346 return r;
347 }
348
349 r = mailimf_string_write(f, col, "\r\n", 2);
350 if (r != MAILIMF_NO_ERROR)
351 return r;
352#if 0
353 * col = 0;
354#endif
355
356 return MAILIMF_NO_ERROR;
357}
358
359static int mailmime_disposition_write(FILE * f, int * col,
360 struct mailmime_disposition *
361 disposition)
362{
363 struct mailmime_disposition_type * dsp_type;
364 int r;
365 clistiter * cur;
366
367 dsp_type = disposition->dsp_type;
368
369 r = mailimf_string_write(f, col, "Content-Disposition: ", 21);
370 if (r != MAILIMF_NO_ERROR)
371 return r;
372
373 switch (dsp_type->dsp_type) {
374 case MAILMIME_DISPOSITION_TYPE_INLINE:
375 r = mailimf_string_write(f, col, "inline", 6);
376 break;
377
378 case MAILMIME_DISPOSITION_TYPE_ATTACHMENT:
379 r = mailimf_string_write(f, col, "attachment", 10);
380 break;
381
382 case MAILMIME_DISPOSITION_TYPE_EXTENSION:
383 r = mailimf_string_write(f, col, dsp_type->dsp_extension,
384 strlen(dsp_type->dsp_extension));
385 break;
386
387 default:
388 r = MAILIMF_ERROR_INVAL;
389 break;
390 }
391
392 if (r != MAILIMF_NO_ERROR)
393 return r;
394
395 for(cur = clist_begin(disposition->dsp_parms) ;
396 cur != NULL ; cur = clist_next(cur)) {
397 struct mailmime_disposition_parm * param;
398
399 param = cur->data;
400
401 r = mailimf_string_write(f, col, "; ", 2);
402 if (r != MAILIMF_NO_ERROR)
403 return r;
404
405 r = mailmime_disposition_param_write(f, col, param);
406 if (r != MAILIMF_NO_ERROR)
407 return r;
408 }
409
410 r = mailimf_string_write(f, col, "\r\n", 2);
411 if (r != MAILIMF_NO_ERROR)
412 return r;
413
414 return MAILIMF_NO_ERROR;
415}
416
417static int
418mailmime_disposition_param_write(FILE * f, int * col,
419 struct mailmime_disposition_parm * param)
420{
421 size_t len;
422 char sizestr[20];
423 int r;
424
425 switch (param->pa_type) {
426 case MAILMIME_DISPOSITION_PARM_FILENAME:
427 len = strlen("filename=") + strlen(param->pa_data.pa_filename);
428 break;
429
430 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
431 len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date);
432 break;
433
434 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
435 len = strlen("modification-date=") +
436 strlen(param->pa_data.pa_modification_date);
437 break;
438
439 case MAILMIME_DISPOSITION_PARM_READ_DATE:
440 len = strlen("read-date=") + strlen(param->pa_data.pa_read_date);
441 break;
442
443 case MAILMIME_DISPOSITION_PARM_SIZE:
444 snprintf(sizestr, 20, "%lu", (unsigned long) param->pa_data.pa_size);
445 len = strlen("size=") + strlen(sizestr);
446 break;
447
448 case MAILMIME_DISPOSITION_PARM_PARAMETER:
449 len = strlen(param->pa_data.pa_parameter->pa_name) + 1 +
450 strlen(param->pa_data.pa_parameter->pa_value);
451 break;
452
453 default:
454 return MAILIMF_ERROR_INVAL;
455 }
456
457 if (* col > 1) {
458
459 if (* col + len > MAX_MAIL_COL) {
460 r = mailimf_string_write(f, col, "\r\n ", 3);
461 if (r != MAILIMF_NO_ERROR)
462 return r;
463#if 0
464 * col = 1;
465#endif
466 }
467 }
468
469 switch (param->pa_type) {
470 case MAILMIME_DISPOSITION_PARM_FILENAME:
471 r = mailimf_string_write(f, col, "filename=", 9);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474
475 r = mailimf_quoted_string_write(f, col,
476 param->pa_data.pa_filename, strlen(param->pa_data.pa_filename));
477 if (r != MAILIMF_NO_ERROR)
478 return r;
479 break;
480
481 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
482 r = mailimf_string_write(f, col, "creation-date=", 14);
483 if (r != MAILIMF_NO_ERROR)
484 return r;
485
486 r = mailimf_quoted_string_write(f, col, param->pa_data.pa_creation_date,
487 strlen(param->pa_data.pa_creation_date));
488 if (r != MAILIMF_NO_ERROR)
489 return r;
490 break;
491
492 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
493 r = mailimf_string_write(f, col, "modification-date=", 18);
494 if (r != MAILIMF_NO_ERROR)
495 return r;
496
497 r = mailimf_quoted_string_write(f, col,
498 param->pa_data.pa_modification_date,
499 strlen(param->pa_data.pa_modification_date));
500 if (r != MAILIMF_NO_ERROR)
501 return r;
502 break;
503
504 case MAILMIME_DISPOSITION_PARM_READ_DATE:
505 r = mailimf_string_write(f, col, "read-date=", 10);
506 if (r != MAILIMF_NO_ERROR)
507 return r;
508
509 r = mailimf_quoted_string_write(f, col, param->pa_data.pa_read_date,
510 strlen(param->pa_data.pa_read_date));
511 if (r != MAILIMF_NO_ERROR)
512 return r;
513 break;
514
515 case MAILMIME_DISPOSITION_PARM_SIZE:
516 r = mailimf_string_write(f, col, "size=", 5);
517 if (r != MAILIMF_NO_ERROR)
518 return r;
519
520 r = mailimf_string_write(f, col, sizestr, strlen(sizestr));
521 if (r != MAILIMF_NO_ERROR)
522 return r;
523 break;
524
525 case MAILMIME_DISPOSITION_PARM_PARAMETER:
526 r = mailmime_parameter_write(f, col, param->pa_data.pa_parameter);
527 if (r != MAILIMF_NO_ERROR)
528 return r;
529 break;
530 }
531
532 return MAILIMF_NO_ERROR;
533}
534
535static int mailmime_parameter_write(FILE * f, int * col,
536 struct mailmime_parameter * param)
537{
538 int r;
539
540 r = mailimf_string_write(f, col, param->pa_name,
541 strlen(param->pa_name));
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544
545 r = mailimf_string_write(f, col, "=", 1);
546 if (r != MAILIMF_NO_ERROR)
547 return r;
548
549 r = mailimf_quoted_string_write(f, col, param->pa_value,
550 strlen(param->pa_value));
551 if (r != MAILIMF_NO_ERROR)
552 return r;
553
554 return MAILIMF_NO_ERROR;
555}
556
557int mailmime_content_type_write(FILE * f, int * col,
558 struct mailmime_content * content)
559{
560 clistiter * cur;
561 size_t len;
562 int r;
563
564 r = mailmime_type_write(f, col, content->ct_type);
565 if (r != MAILIMF_NO_ERROR)
566 return r;
567
568 r = mailimf_string_write(f, col, "/", 1);
569 if (r != MAILIMF_NO_ERROR)
570 return r;
571
572 r = mailimf_string_write(f, col, content->ct_subtype,
573 strlen(content->ct_subtype));
574 if (r != MAILIMF_NO_ERROR)
575 return r;
576
577 if (content->ct_parameters != NULL) {
578 for(cur = clist_begin(content->ct_parameters) ;
579 cur != NULL ; cur = clist_next(cur)) {
580 struct mailmime_parameter * param;
581
582 param = cur->data;
583
584 r = mailimf_string_write(f, col, "; ", 2);
585 if (r != MAILIMF_NO_ERROR)
586 return r;
587
588 len = strlen(param->pa_name) + 1 + strlen(param->pa_value);
589
590 if (* col > 1) {
591
592 if (* col + len > MAX_MAIL_COL) {
593 r = mailimf_string_write(f, col, "\r\n ", 3);
594 if (r != MAILIMF_NO_ERROR)
595 return r;
596#if 0
597 * col = 1;
598#endif
599 }
600 }
601
602 r = mailmime_parameter_write(f, col, param);
603 if (r != MAILIMF_NO_ERROR)
604 return r;
605 }
606 }
607
608 return MAILIMF_NO_ERROR;
609}
610
611int mailmime_content_write(FILE * f, int * col,
612 struct mailmime_content * content)
613{
614 int r;
615
616 r = mailimf_string_write(f, col, "Content-Type: ", 14);
617 if (r != MAILIMF_NO_ERROR)
618 return r;
619
620 r = mailmime_content_type_write(f, col, content);
621 if (r != MAILIMF_NO_ERROR)
622 return r;
623
624 r = mailimf_string_write(f, col, "\r\n", 2);
625 if (r != MAILIMF_NO_ERROR)
626 return r;
627
628 return MAILIMF_NO_ERROR;
629}
630
631static int mailmime_type_write(FILE * f, int * col,
632 struct mailmime_type * type)
633{
634 int r;
635
636 switch (type->tp_type) {
637 case MAILMIME_TYPE_DISCRETE_TYPE:
638 r = mailmime_discrete_type_write(f, col, type->tp_data.tp_discrete_type);
639 break;
640
641 case MAILMIME_TYPE_COMPOSITE_TYPE:
642 r = mailmime_composite_type_write(f, col, type->tp_data.tp_composite_type);
643 break;
644
645 default:
646 r = MAILIMF_ERROR_INVAL;
647 break;
648 }
649
650 if (r != MAILIMF_NO_ERROR)
651 return r;
652
653 return MAILIMF_NO_ERROR;
654}
655
656static int
657mailmime_discrete_type_write(FILE * f, int * col,
658 struct mailmime_discrete_type * discrete_type)
659{
660 int r;
661
662 switch (discrete_type->dt_type) {
663 case MAILMIME_DISCRETE_TYPE_TEXT:
664 r = mailimf_string_write(f, col, "text", 4);
665 break;
666
667 case MAILMIME_DISCRETE_TYPE_IMAGE:
668 r = mailimf_string_write(f, col, "image", 5);
669 break;
670
671 case MAILMIME_DISCRETE_TYPE_AUDIO:
672 r = mailimf_string_write(f, col, "audio", 5);
673 break;
674
675 case MAILMIME_DISCRETE_TYPE_VIDEO:
676 r = mailimf_string_write(f, col, "video", 5);
677 break;
678
679 case MAILMIME_DISCRETE_TYPE_APPLICATION:
680 r = mailimf_string_write(f, col, "application", 11);
681 break;
682
683 case MAILMIME_DISCRETE_TYPE_EXTENSION:
684 r = mailimf_string_write(f, col, discrete_type->dt_extension,
685 strlen(discrete_type->dt_extension));
686 break;
687
688 default:
689 r = MAILIMF_ERROR_INVAL;
690 break;
691 }
692
693 if (r != MAILIMF_NO_ERROR)
694 return r;
695
696 return MAILIMF_NO_ERROR;
697}
698
699static int
700mailmime_composite_type_write(FILE * f, int * col,
701 struct mailmime_composite_type * composite_type)
702{
703 int r;
704
705 switch (composite_type->ct_type) {
706 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
707 r = mailimf_string_write(f, col, "message", 7);
708 break;
709
710 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
711 r = mailimf_string_write(f, col, "multipart", 9);
712 break;
713
714 case MAILMIME_COMPOSITE_TYPE_EXTENSION:
715 r = mailimf_string_write(f, col, composite_type->ct_token,
716 strlen(composite_type->ct_token));
717 break;
718
719 default:
720 r = MAILIMF_ERROR_INVAL;
721 break;
722 }
723
724 if (r != MAILIMF_NO_ERROR)
725 return r;
726
727 return MAILIMF_NO_ERROR;
728}
729
730
731
732
733/* ****************************************************************** */
734/* message */
735
736/*
737static int mailmime_data_write(FILE * f, int * col,
738 struct mailmime_data * data,
739 int is_text);
740*/
741
742static int mailmime_text_content_write(FILE * f, int * col, int encoding,
743 int istext,
744 const char * text, size_t size);
745
746/*
747static int mailmime_base64_write(FILE * f, int * col,
748 char * text, size_t size);
749
750static int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
751 char * text, size_t size);
752*/
753
754static int mailmime_part_write(FILE * f, int * col,
755 struct mailmime * build_info)
756{
757 clistiter * cur;
758 int first;
759 int r;
760 char * boundary;
761 int istext;
762
763 istext = TRUE;
764 boundary = NULL;
765
766 if (build_info->mm_content_type != NULL) {
767 if (build_info->mm_type == MAILMIME_MULTIPLE) {
768 boundary = mailmime_extract_boundary(build_info->mm_content_type);
769 if (boundary == NULL)
770 return MAILIMF_ERROR_INVAL;
771 }
772
773 if (build_info->mm_content_type->ct_type->tp_type ==
774 MAILMIME_TYPE_DISCRETE_TYPE) {
775 if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type !=
776 MAILMIME_DISCRETE_TYPE_TEXT)
777 istext = FALSE;
778 }
779 }
780
781 switch (build_info->mm_type) {
782 case MAILMIME_SINGLE:
783
784 /* 1-part body */
785
786 if (build_info->mm_data.mm_single != NULL) {
787 r = mailmime_data_write(f, col, build_info->mm_data.mm_single, istext);
788 if (r != MAILIMF_NO_ERROR)
789 return r;
790 }
791
792 break;
793
794 case MAILMIME_MULTIPLE:
795
796 /* multi-part */
797
798
799 /* preamble */
800
801 if (build_info->mm_data.mm_multipart.mm_preamble != NULL) {
802 r = mailmime_data_write(f, col,
803 build_info->mm_data.mm_multipart.mm_preamble, TRUE);
804 if (r != MAILIMF_NO_ERROR)
805 return r;
806
807 r = mailimf_string_write(f, col, "\r\n", 2);
808 if (r != MAILIMF_NO_ERROR)
809 return r;
810#if 0
811 * col = 0;
812#endif
813 }
814
815 /* sub-parts */
816
817 first = TRUE;
818
819 for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ;
820 cur != NULL ; cur = clist_next(cur)) {
821 struct mailmime * subpart;
822
823 subpart = cur->data;
824
825 if (!first) {
826 r = mailimf_string_write(f, col, "\r\n", 2);
827 if (r != MAILIMF_NO_ERROR)
828 return r;
829#if 0
830 * col = 0;
831#endif
832 }
833 else {
834 first = FALSE;
835 }
836
837 r = mailimf_string_write(f, col, "--", 2);
838 if (r != MAILIMF_NO_ERROR)
839 return r;
840
841 r = mailimf_string_write(f, col, boundary, strlen(boundary));
842 if (r != MAILIMF_NO_ERROR)
843 return r;
844
845 r = mailimf_string_write(f, col, "\r\n", 2);
846 if (r != MAILIMF_NO_ERROR)
847 return r;
848#if 0
849 * col = 0;
850#endif
851
852 r = mailmime_sub_write(f, col, subpart);
853 if (r != MAILIMF_NO_ERROR)
854 return r;
855 }
856
857 r = mailimf_string_write(f, col, "\r\n", 2);
858 if (r != MAILIMF_NO_ERROR)
859 return r;
860#if 0
861 * col = 0;
862#endif
863
864 r = mailimf_string_write(f, col, "--", 2);
865 if (r != MAILIMF_NO_ERROR)
866 return r;
867
868 r = mailimf_string_write(f, col, boundary, strlen(boundary));
869 if (r != MAILIMF_NO_ERROR)
870 return r;
871
872 r = mailimf_string_write(f, col, "--", 2);
873 if (r != MAILIMF_NO_ERROR)
874 return r;
875
876
877 /* epilogue */
878
879 r = mailimf_string_write(f, col, "\r\n", 2);
880 if (r != MAILIMF_NO_ERROR)
881 return r;
882#if 0
883 * col = 0;
884#endif
885
886 if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) {
887 r = mailmime_data_write(f, col,
888 build_info->mm_data.mm_multipart.mm_epilogue, TRUE);
889 if (r != MAILIMF_NO_ERROR)
890 return r;
891 }
892
893 break;
894
895 case MAILMIME_MESSAGE:
896
897 if (build_info->mm_data.mm_message.mm_fields != NULL) {
898 r = mailimf_fields_write(f, col,
899 build_info->mm_data.mm_message.mm_fields);
900 if (r != MAILIMF_NO_ERROR)
901 return r;
902 }
903
904 if (build_info->mm_mime_fields != NULL) {
905 r = mailmime_fields_write(f, col, build_info->mm_mime_fields);
906 if (r != MAILIMF_NO_ERROR)
907 return r;
908 }
909
910 /* encapsuled message */
911
912 if (build_info->mm_data.mm_message.mm_msg_mime != NULL) {
913 r = mailmime_sub_write(f, col,
914 build_info->mm_data.mm_message.mm_msg_mime);
915 if (r != MAILIMF_NO_ERROR)
916 return r;
917 }
918 break;
919
920 }
921
922 return MAILIMF_NO_ERROR;
923}
924
925
926static int mailmime_sub_write(FILE * f, int * col,
927 struct mailmime * build_info)
928{
929 int r;
930
931#if 0
932 * col = 0;
933#endif
934 /* MIME field - Content-Type */
935
936 if (build_info->mm_content_type != NULL) {
937 r = mailmime_content_write(f, col, build_info->mm_content_type);
938 if (r != MAILIMF_NO_ERROR)
939 return r;
940 }
941
942 /* other MIME fields */
943
944 if (build_info->mm_type != MAILMIME_MESSAGE) {
945 if (build_info->mm_mime_fields != NULL) {
946 r = mailmime_fields_write(f, col, build_info->mm_mime_fields);
947 if (r != MAILIMF_NO_ERROR)
948 return r;
949 }
950 }
951
952 r = mailimf_string_write(f, col, "\r\n", 2);
953 if (r != MAILIMF_NO_ERROR)
954 return r;
955#if 0
956 * col = 0;
957#endif
958
959 return mailmime_part_write(f, col, build_info);
960}
961
962int mailmime_write(FILE * f, int * col,
963 struct mailmime * build_info)
964{
965 if (build_info->mm_parent != NULL)
966 return mailmime_sub_write(f, col, build_info);
967 else
968 return mailmime_part_write(f, col, build_info);
969}
970
971
972int mailmime_data_write(FILE * f, int * col,
973 struct mailmime_data * data,
974 int istext)
975{
976 int fd;
977 int r;
978 char * text;
979 struct stat buf;
980 int res;
981
982 switch (data->dt_type) {
983 case MAILMIME_DATA_TEXT:
984
985 if (data->dt_encoded) {
986 r = mailimf_string_write(f, col,
987 data->dt_data.dt_text.dt_data,
988 data->dt_data.dt_text.dt_length);
989 if (r != MAILIMF_NO_ERROR)
990 return r;
991 }
992 else {
993 r = mailmime_text_content_write(f, col, data->dt_encoding, istext,
994 data->dt_data.dt_text.dt_data,
995 data->dt_data.dt_text.dt_length);
996 if (r != MAILIMF_NO_ERROR)
997 return r;
998 }
999
1000 break;
1001
1002 case MAILMIME_DATA_FILE:
1003 fd = open(data->dt_data.dt_filename, O_RDONLY);
1004 if (fd < 0) {
1005 res = MAILIMF_ERROR_FILE;
1006 goto err;
1007 }
1008
1009 r = fstat(fd, &buf);
1010 if (r < 0) {
1011 res = MAILIMF_ERROR_FILE;
1012 goto close;
1013 }
1014
1015 if (buf.st_size != 0) {
1016 text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1017 if (text == MAP_FAILED) {
1018 res = MAILIMF_ERROR_FILE;
1019 goto close;
1020 }
1021
1022 if (data->dt_encoded) {
1023 r = mailimf_string_write(f, col, text, buf.st_size);
1024 if (r != MAILIMF_NO_ERROR) {
1025 res = r;
1026 goto unmap;
1027 }
1028 }
1029 else {
1030 r = mailmime_text_content_write(f, col, data->dt_encoding, istext,
1031 text, buf.st_size);
1032 if (r != MAILIMF_NO_ERROR) {
1033 res = r;
1034 goto unmap;
1035 }
1036 }
1037
1038 munmap(text, buf.st_size);
1039 }
1040 close(fd);
1041
1042 if (r != MAILIMF_NO_ERROR)
1043 return r;
1044
1045 break;
1046
1047 unmap:
1048 munmap(text, buf.st_size);
1049 close:
1050 close(fd);
1051 err:
1052 return res;
1053 }
1054
1055 return MAILIMF_NO_ERROR;
1056}
1057
1058static int mailmime_text_content_write(FILE * f, int * col, int encoding,
1059 int istext,
1060 const char * text, size_t size)
1061{
1062 switch (encoding) {
1063 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
1064 return mailmime_quoted_printable_write(f, col, istext, text, size);
1065 break;
1066
1067 case MAILMIME_MECHANISM_BASE64:
1068 return mailmime_base64_write(f, col, text, size);
1069 break;
1070
1071 case MAILMIME_MECHANISM_7BIT:
1072 case MAILMIME_MECHANISM_8BIT:
1073 case MAILMIME_MECHANISM_BINARY:
1074 default:
1075 return mailimf_string_write(f, col, text, size);
1076 }
1077}
1078
1079
1080static const char base64_encoding[] =
1081"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1082
1083#define BASE64_MAX_COL 76
1084
1085int mailmime_base64_write(FILE * f, int * col,
1086 const char * text, size_t size)
1087{
1088 int a;
1089 int b;
1090 int c;
1091 size_t remains;
1092 const char * p;
1093 size_t count;
1094 char ogroup[4];
1095 int r;
1096
1097 remains = size;
1098 p = text;
1099
1100 while (remains > 0) {
1101 switch (remains) {
1102 case 1:
1103 a = (unsigned char) p[0];
1104 b = 0;
1105 c = 0;
1106 count = 1;
1107 break;
1108 case 2:
1109 a = (unsigned char) p[0];
1110 b = (unsigned char) p[1];
1111 c = 0;
1112 count = 2;
1113 break;
1114 default:
1115 a = (unsigned char) p[0];
1116 b = (unsigned char) p[1];
1117 c = (unsigned char) p[2];
1118 count = 3;
1119 break;
1120 }
1121
1122 ogroup[0]= base64_encoding[a >> 2];
1123 ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)];
1124 ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)];
1125 ogroup[3]= base64_encoding[c & 0x3F];
1126
1127 switch (count) {
1128 case 1:
1129 ogroup[2]= '=';
1130 ogroup[3]= '=';
1131 break;
1132 case 2:
1133 ogroup[3]= '=';
1134 break;
1135 }
1136
1137 if (* col + 4 > BASE64_MAX_COL) {
1138 r = mailimf_string_write(f, col, "\r\n", 2);
1139 if (r != MAILIMF_NO_ERROR)
1140 return r;
1141#if 0
1142 * col = 0;
1143#endif
1144 }
1145
1146 r = mailimf_string_write(f, col, ogroup, 4);
1147 if (r != MAILIMF_NO_ERROR)
1148 return r;
1149
1150 remains -= count;
1151 p += count;
1152 }
1153
1154 r = mailimf_string_write(f, col, "\r\n", 2);
1155
1156 return MAILIMF_NO_ERROR;
1157}
1158
1159#if 0
1160#define MAX_WRITE_SIZE 512
1161#endif
1162
1163enum {
1164 STATE_INIT,
1165 STATE_CR,
1166 STATE_SPACE,
1167 STATE_SPACE_CR,
1168};
1169
1170#if 0
1171static inline int write_try_buf(FILE * f, int * col,
1172 char ** pstart, size_t * plen)
1173{
1174 int r;
1175
1176 if (* plen >= MAX_WRITE_SIZE) {
1177 r = mailimf_string_write(f, col, * pstart, * plen);
1178 if (r != MAILIMF_NO_ERROR)
1179 return r;
1180 * plen = 0;
1181 }
1182
1183 return MAILIMF_NO_ERROR;
1184}
1185#endif
1186
1187static inline int write_remaining(FILE * f, int * col,
1188 const char ** pstart, size_t * plen)
1189{
1190 int r;
1191
1192 if (* plen > 0) {
1193 r = mailimf_string_write(f, col, * pstart, * plen);
1194 if (r != MAILIMF_NO_ERROR)
1195 return r;
1196 * plen = 0;
1197 }
1198
1199 return MAILIMF_NO_ERROR;
1200}
1201
1202
1203
1204#define QP_MAX_COL 72
1205
1206int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
1207 const char * text, size_t size)
1208{
1209 size_t i;
1210 const char * start;
1211 size_t len;
1212 char hexstr[6];
1213 int r;
1214 int state;
1215
1216 start = text;
1217 len = 0;
1218 state = STATE_INIT;
1219
1220 i = 0;
1221 while (i < size) {
1222 unsigned char ch;
1223
1224 if (* col + len > QP_MAX_COL) {
1225 r = write_remaining(f, col, &start, &len);
1226 if (r != MAILIMF_NO_ERROR)
1227 return r;
1228 start = text + i;
1229
1230 r = mailimf_string_write(f, col, "=\r\n", 3);
1231 if (r != MAILIMF_NO_ERROR)
1232 return r;
1233 }
1234
1235 ch = text[i];
1236
1237 switch (state) {
1238
1239 case STATE_INIT:
1240 switch (ch) {
1241 case ' ':
1242 case '\t':
1243 state = STATE_SPACE;
1244 break;
1245
1246 case '\r':
1247 state = STATE_CR;
1248 break;
1249
1250 case '!':
1251 case '"':
1252 case '#':
1253 case '$':
1254 case '@':
1255 case '[':
1256 case '\\':
1257 case ']':
1258 case '^':
1259 case '`':
1260 case '{':
1261 case '|':
1262 case '}':
1263 case '~':
1264 case '=':
1265 case '?':
1266 case '_':
1267 case 'F': /* there is no more 'From' at the beginning of a line */
1268 r = write_remaining(f, col, &start, &len);
1269 if (r != MAILIMF_NO_ERROR)
1270 return r;
1271 start = text + i + 1;
1272
1273 snprintf(hexstr, 6, "=%02X", ch);
1274
1275 r = mailimf_string_write(f, col, hexstr, 3);
1276 if (r != MAILIMF_NO_ERROR)
1277 return r;
1278 break;
1279
1280 default:
1281 if (istext && (ch == '\n')) {
1282 r = write_remaining(f, col, &start, &len);
1283 if (r != MAILIMF_NO_ERROR)
1284 return r;
1285 start = text + i + 1;
1286
1287 r = mailimf_string_write(f, col, "\r\n", 2);
1288 if (r != MAILIMF_NO_ERROR)
1289 return r;
1290 break;
1291 }
1292 else {
1293 if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) {
1294 len ++;
1295 }
1296 else {
1297 r = write_remaining(f, col, &start, &len);
1298 if (r != MAILIMF_NO_ERROR)
1299 return r;
1300 start = text + i + 1;
1301
1302 snprintf(hexstr, 6, "=%02X", ch);
1303
1304 r = mailimf_string_write(f, col, hexstr, 3);
1305 if (r != MAILIMF_NO_ERROR)
1306 return r;
1307 }
1308 }
1309
1310 break;
1311 }
1312
1313 i ++;
1314 break;
1315
1316 case STATE_CR:
1317 switch (ch) {
1318 case '\n':
1319 r = write_remaining(f, col, &start, &len);
1320 if (r != MAILIMF_NO_ERROR)
1321 return r;
1322 start = text + i + 1;
1323 r = mailimf_string_write(f, col, "\r\n", 2);
1324 if (r != MAILIMF_NO_ERROR)
1325 return r;
1326 i ++;
1327 state = STATE_INIT;
1328 break;
1329
1330 default:
1331 r = write_remaining(f, col, &start, &len);
1332 if (r != MAILIMF_NO_ERROR)
1333 return r;
1334 start = text + i;
1335 snprintf(hexstr, 6, "=%02X", '\r');
1336 r = mailimf_string_write(f, col, hexstr, 3);
1337 if (r != MAILIMF_NO_ERROR)
1338 return r;
1339 state = STATE_INIT;
1340 break;
1341 }
1342 break;
1343
1344 case STATE_SPACE:
1345 switch (ch) {
1346 case '\r':
1347 state = STATE_SPACE_CR;
1348 i ++;
1349 break;
1350
1351 case '\n':
1352 r = write_remaining(f, col, &start, &len);
1353 if (r != MAILIMF_NO_ERROR)
1354 return r;
1355 start = text + i + 1;
1356 snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]);
1357 r = mailimf_string_write(f, col, hexstr, strlen(hexstr));
1358 if (r != MAILIMF_NO_ERROR)
1359 return r;
1360 state = STATE_INIT;
1361 i ++;
1362 break;
1363
1364 case ' ':
1365 case '\t':
1366 len ++;
1367 i ++;
1368 break;
1369
1370 default:
1371#if 0
1372 len += 2;
1373 state = STATE_INIT;
1374 i ++;
1375#endif
1376 len ++;
1377 state = STATE_INIT;
1378 break;
1379 }
1380
1381 break;
1382
1383 case STATE_SPACE_CR:
1384 switch (ch) {
1385 case '\n':
1386 r = write_remaining(f, col, &start, &len);
1387 if (r != MAILIMF_NO_ERROR)
1388 return r;
1389 start = text + i + 1;
1390 snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]);
1391 r = mailimf_string_write(f, col, hexstr, strlen(hexstr));
1392 if (r != MAILIMF_NO_ERROR)
1393 return r;
1394 state = STATE_INIT;
1395 i ++;
1396 break;
1397
1398 default:
1399 r = write_remaining(f, col, &start, &len);
1400 if (r != MAILIMF_NO_ERROR)
1401 return r;
1402 start = text + i + 1;
1403 snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r');
1404 r = mailimf_string_write(f, col, hexstr, strlen(hexstr));
1405 if (r != MAILIMF_NO_ERROR)
1406 return r;
1407 state = STATE_INIT;
1408 break;
1409 }
1410
1411 break;
1412 }
1413 }
1414
1415 return MAILIMF_NO_ERROR;
1416}
diff --git a/libetpan/src/low-level/mime/mailmime_write.h b/libetpan/src/low-level/mime/mailmime_write.h
new file mode 100644
index 0000000..adca123
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_H
37
38#define MAILMIME_WRITE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47int mailmime_fields_write(FILE * f, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write(FILE * f, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write(FILE * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write(FILE * f, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write(FILE * f, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write(FILE * f, int * col,
66 struct mailmime_data * data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write_file.c b/libetpan/src/low-level/mime/mailmime_write_file.c
new file mode 100644
index 0000000..3beeff8
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_file.c
@@ -0,0 +1,156 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_write_file.h"
37
38#include <stdlib.h>
39#include <string.h>
40#include <time.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46
47#include "mailmime_content.h"
48#include "mailmime_types_helper.h"
49#include "mailmime_write_generic.h"
50
51static int do_write(void * data, const char * str, size_t length)
52{
53 FILE * f;
54
55 f = data;
56
57 return fwrite(str, 1, length, f);
58}
59
60
61int mailmime_fields_write_file(FILE * f, int * col,
62 struct mailmime_fields * fields)
63{
64 return mailmime_fields_write_driver(do_write, f, col, fields);
65}
66
67int mailmime_content_write_file(FILE * f, int * col,
68 struct mailmime_content * content)
69{
70 return mailmime_content_write_driver(do_write, f, col, content);
71}
72
73int mailmime_content_type_write_file(FILE * f, int * col,
74 struct mailmime_content * content)
75{
76 return mailmime_content_type_write_driver(do_write, f, col, content);
77}
78
79int mailmime_write_file(FILE * f, int * col,
80 struct mailmime * build_info)
81{
82 return mailmime_write_driver(do_write, f, col, build_info);
83}
84
85int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext,
86 const char * text, size_t size)
87{
88 return mailmime_quoted_printable_write_driver(do_write, f, col,
89 istext, text, size);
90}
91
92int mailmime_base64_write_file(FILE * f, int * col,
93 const char * text, size_t size)
94{
95 return mailmime_base64_write_driver(do_write, f, col, text, size);
96}
97
98int mailmime_data_write_file(FILE * f, int * col,
99 struct mailmime_data * data,
100 int istext)
101{
102 return mailmime_data_write_driver(do_write, f, col, data, istext);
103}
104
105
106
107
108/* binary compatibility with 0.34 - begin */
109
110#ifdef MAILMIME_WRITE_COMPATIBILITY
111int mailmime_fields_write(FILE * f, int * col,
112 struct mailmime_fields * fields)
113{
114 return mailmime_fields_write_file(f, col, fields);
115}
116
117int mailmime_content_write(FILE * f, int * col,
118 struct mailmime_content * content)
119{
120 return mailmime_content_write_file(f, col, content);
121}
122
123int mailmime_content_type_write(FILE * f, int * col,
124 struct mailmime_content * content)
125{
126 return mailmime_content_type_write_file(f, col, content);
127}
128
129int mailmime_write(FILE * f, int * col,
130 struct mailmime * build_info)
131{
132 return mailmime_write_file(f, col, build_info);
133}
134
135int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
136 const char * text, size_t size)
137{
138 return mailmime_quoted_printable_write_file(f, col,
139 istext, text, size);
140}
141
142int mailmime_base64_write(FILE * f, int * col,
143 const char * text, size_t size)
144{
145 return mailmime_base64_write_file(f, col, text, size);
146}
147
148int mailmime_data_write(FILE * f, int * col,
149 struct mailmime_data * data,
150 int istext)
151{
152 return mailmime_data_write_file(f, col, data, istext);
153}
154#endif
155
156/* binary compatibility with 0.34 - end */
diff --git a/libetpan/src/low-level/mime/mailmime_write_file.h b/libetpan/src/low-level/mime/mailmime_write_file.h
new file mode 100644
index 0000000..4cfa484
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_file.h
@@ -0,0 +1,105 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_FILE_H
37
38#define MAILMIME_WRITE_FILE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47 //#define MAILMIME_WRITE_COMPATIBILITY
48
49
50int mailmime_fields_write_file(FILE * f, int * col,
51 struct mailmime_fields * fields);
52
53int mailmime_content_write_file(FILE * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_content_type_write_file(FILE * f, int * col,
57 struct mailmime_content * content);
58
59int mailmime_write_file(FILE * f, int * col,
60 struct mailmime * build_info);
61
62int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext,
63 const char * text, size_t size);
64
65int mailmime_base64_write_file(FILE * f, int * col,
66 const char * text, size_t size);
67
68int mailmime_data_write_file(FILE * f, int * col,
69 struct mailmime_data * data,
70 int istext);
71
72
73/* binary compatibility with 0.34 - begin */
74
75#ifdef MAILMIME_WRITE_COMPATIBILITY
76int mailmime_fields_write(FILE * f, int * col,
77 struct mailmime_fields * fields);
78
79int mailmime_content_write(FILE * f, int * col,
80 struct mailmime_content * content);
81
82int mailmime_content_type_write(FILE * f, int * col,
83 struct mailmime_content * content);
84
85int mailmime_write(FILE * f, int * col,
86 struct mailmime * build_info);
87
88int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
89 const char * text, size_t size);
90
91int mailmime_base64_write(FILE * f, int * col,
92 const char * text, size_t size);
93
94int mailmime_data_write(FILE * f, int * col,
95 struct mailmime_data * data,
96 int istext);
97#endif
98
99/* binary compatibility with 0.34 - end */
100
101#ifdef __cplusplus
102}
103#endif
104
105#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write_generic.c b/libetpan/src/low-level/mime/mailmime_write_generic.c
new file mode 100644
index 0000000..4a55881
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_generic.c
@@ -0,0 +1,1416 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_write_generic.h"
37
38#include <stdlib.h>
39#include <string.h>
40#include <time.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46
47#include "mailimf_write_generic.h"
48#include "mailmime_content.h"
49#include "mailmime_types_helper.h"
50
51#define MAX_MAIL_COL 78
52
53#ifndef TRUE
54#define TRUE 1
55#endif
56
57#ifndef FALSE
58#define FALSE 0
59#endif
60
61static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
62 struct mailmime_field * field);
63
64static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id);
65
66static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr);
67
68static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version);
69
70static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
71 struct mailmime_mechanism * encoding);
72
73static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
74 struct mailmime_language * language);
75
76static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
77 struct mailmime_disposition *
78 disposition);
79
80static int
81mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
82 struct mailmime_disposition_parm * param);
83
84static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
85 struct mailmime_parameter * param);
86
87/*
88static int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
89 struct mailmime_content * content);
90*/
91
92static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
93 struct mailmime_type * type);
94
95static int
96mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
97 struct mailmime_discrete_type * discrete_type);
98
99static int
100mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
101 struct mailmime_composite_type * composite_type);
102
103static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
104 struct mailmime * build_info);
105
106
107/* ***** */
108
109int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, struct mailmime_fields * fields)
110{
111 int r;
112 clistiter * cur;
113
114 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
115 cur = clist_next(cur)) {
116 struct mailmime_field * field;
117
118 field = cur->data;
119 r = mailmime_field_write_driver(do_write, data, col, field);
120 if (r != MAILIMF_NO_ERROR)
121 return r;
122 }
123
124 return MAILIMF_NO_ERROR;
125}
126
127static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
128 struct mailmime_field * field)
129{
130 int r;
131
132 switch (field->fld_type) {
133 case MAILMIME_FIELD_TYPE:
134 r = mailmime_content_write_driver(do_write, data, col, field->fld_data.fld_content);
135 break;
136
137 case MAILMIME_FIELD_TRANSFER_ENCODING:
138 r = mailmime_encoding_write_driver(do_write, data, col, field->fld_data.fld_encoding);
139 break;
140
141 case MAILMIME_FIELD_ID:
142 r = mailmime_id_write_driver(do_write, data, col, field->fld_data.fld_id);
143 break;
144
145 case MAILMIME_FIELD_DESCRIPTION:
146 r = mailmime_description_write_driver(do_write, data, col, field->fld_data.fld_description);
147 break;
148
149 case MAILMIME_FIELD_VERSION:
150 r = mailmime_version_write_driver(do_write, data, col, field->fld_data.fld_version);
151 break;
152
153 case MAILMIME_FIELD_DISPOSITION:
154 r = mailmime_disposition_write_driver(do_write, data, col, field->fld_data.fld_disposition);
155 break;
156
157 case MAILMIME_FIELD_LANGUAGE:
158 r = mailmime_language_write_driver(do_write, data, col, field->fld_data.fld_language);
159 break;
160
161 default:
162 r = MAILIMF_ERROR_INVAL;
163 break;
164 }
165
166 if (r != MAILIMF_NO_ERROR)
167 return r;
168
169 return MAILIMF_NO_ERROR;
170}
171
172static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id)
173{
174 int r;
175
176 r = mailimf_string_write_driver(do_write, data, col, "Content-ID: ", 12);
177 if (r != MAILIMF_NO_ERROR)
178 return r;
179
180 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
181 if (r != MAILIMF_NO_ERROR)
182 return r;
183
184 r = mailimf_string_write_driver(do_write, data, col, id, strlen(id));
185 if (r != MAILIMF_NO_ERROR)
186 return r;
187
188 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
189 if (r != MAILIMF_NO_ERROR)
190 return r;
191
192 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
193 if (r != MAILIMF_NO_ERROR)
194 return r;
195#if 0
196 * col = 0;
197#endif
198
199 return MAILIMF_NO_ERROR;
200}
201
202static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr)
203{
204 int r;
205
206 r = mailimf_string_write_driver(do_write, data, col, "Content-Description: ", 21);
207 if (r != MAILIMF_NO_ERROR)
208 return r;
209
210 r = mailimf_string_write_driver(do_write, data, col, descr, strlen(descr));
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
215 if (r != MAILIMF_NO_ERROR)
216 return r;
217#if 0
218 * col = 0;
219#endif
220
221 return MAILIMF_NO_ERROR;
222}
223
224static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version)
225{
226 int r;
227 char versionstr[40];
228
229 r = mailimf_string_write_driver(do_write, data, col, "MIME-Version: ", 14);
230 if (r != MAILIMF_NO_ERROR)
231 return r;
232
233 snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF);
234
235 r = mailimf_string_write_driver(do_write, data, col, versionstr, strlen(versionstr));
236 if (r != MAILIMF_NO_ERROR)
237 return r;
238
239 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
240 if (r != MAILIMF_NO_ERROR)
241 return r;
242#if 0
243 * col = 0;
244#endif
245
246 return MAILIMF_NO_ERROR;
247}
248
249static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
250 struct mailmime_mechanism * encoding)
251{
252 int r;
253
254 r = mailimf_string_write_driver(do_write, data, col, "Content-Transfer-Encoding: ", 27);
255 if (r != MAILIMF_NO_ERROR)
256 return r;
257
258 switch (encoding->enc_type) {
259 case MAILMIME_MECHANISM_7BIT:
260 r = mailimf_string_write_driver(do_write, data, col, "7bit", 4);
261 break;
262
263 case MAILMIME_MECHANISM_8BIT:
264 r = mailimf_string_write_driver(do_write, data, col, "8bit", 4);
265 break;
266
267 case MAILMIME_MECHANISM_BINARY:
268 r = mailimf_string_write_driver(do_write, data, col, "binary", 6);
269 break;
270
271 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
272 r = mailimf_string_write_driver(do_write, data, col, "quoted-printable", 16);
273 break;
274
275 case MAILMIME_MECHANISM_BASE64:
276 r = mailimf_string_write_driver(do_write, data, col, "base64", 6);
277 break;
278
279 case MAILMIME_MECHANISM_TOKEN:
280 r = mailimf_string_write_driver(do_write, data, col, encoding->enc_token,
281 strlen(encoding->enc_token));
282 break;
283
284 default:
285 r = MAILIMF_ERROR_INVAL;
286 break;
287 }
288
289 if (r != MAILIMF_NO_ERROR)
290 return r;
291
292 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
293 if (r != MAILIMF_NO_ERROR)
294 return r;
295#if 0
296 * col = 0;
297#endif
298
299 return MAILIMF_NO_ERROR;
300}
301
302static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
303 struct mailmime_language * language)
304{
305 int r;
306 clistiter * cur;
307 int first;
308
309 r = mailimf_string_write_driver(do_write, data, col, "Content-Language: ", 18);
310 if (r != MAILIMF_NO_ERROR)
311 return r;
312
313 first = TRUE;
314
315 for(cur = clist_begin(language->lg_list) ; cur != NULL ;
316 cur = clist_next(cur)) {
317 char * lang;
318 size_t len;
319
320 lang = clist_content(cur);
321 len = strlen(lang);
322
323 if (!first) {
324 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
325 if (r != MAILIMF_NO_ERROR)
326 return r;
327 }
328 else {
329 first = FALSE;
330 }
331
332 if (* col > 1) {
333
334 if (* col + len > MAX_MAIL_COL) {
335 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
336 if (r != MAILIMF_NO_ERROR)
337 return r;
338#if 0
339 * col = 1;
340#endif
341 }
342 }
343
344 r = mailimf_string_write_driver(do_write, data, col, lang, len);
345 if (r != MAILIMF_NO_ERROR)
346 return r;
347 }
348
349 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
350 if (r != MAILIMF_NO_ERROR)
351 return r;
352#if 0
353 * col = 0;
354#endif
355
356 return MAILIMF_NO_ERROR;
357}
358
359static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
360 struct mailmime_disposition *
361 disposition)
362{
363 struct mailmime_disposition_type * dsp_type;
364 int r;
365 clistiter * cur;
366
367 dsp_type = disposition->dsp_type;
368
369 r = mailimf_string_write_driver(do_write, data, col, "Content-Disposition: ", 21);
370 if (r != MAILIMF_NO_ERROR)
371 return r;
372
373 switch (dsp_type->dsp_type) {
374 case MAILMIME_DISPOSITION_TYPE_INLINE:
375 r = mailimf_string_write_driver(do_write, data, col, "inline", 6);
376 break;
377
378 case MAILMIME_DISPOSITION_TYPE_ATTACHMENT:
379 r = mailimf_string_write_driver(do_write, data, col, "attachment", 10);
380 break;
381
382 case MAILMIME_DISPOSITION_TYPE_EXTENSION:
383 r = mailimf_string_write_driver(do_write, data, col, dsp_type->dsp_extension,
384 strlen(dsp_type->dsp_extension));
385 break;
386
387 default:
388 r = MAILIMF_ERROR_INVAL;
389 break;
390 }
391
392 if (r != MAILIMF_NO_ERROR)
393 return r;
394
395 for(cur = clist_begin(disposition->dsp_parms) ;
396 cur != NULL ; cur = clist_next(cur)) {
397 struct mailmime_disposition_parm * param;
398
399 param = cur->data;
400
401 r = mailimf_string_write_driver(do_write, data, col, "; ", 2);
402 if (r != MAILIMF_NO_ERROR)
403 return r;
404
405 r = mailmime_disposition_param_write_driver(do_write, data, col, param);
406 if (r != MAILIMF_NO_ERROR)
407 return r;
408 }
409
410 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
411 if (r != MAILIMF_NO_ERROR)
412 return r;
413
414 return MAILIMF_NO_ERROR;
415}
416
417static int
418mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
419 struct mailmime_disposition_parm * param)
420{
421 size_t len;
422 char sizestr[20];
423 int r;
424
425 switch (param->pa_type) {
426 case MAILMIME_DISPOSITION_PARM_FILENAME:
427 len = strlen("filename=") + strlen(param->pa_data.pa_filename);
428 break;
429
430 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
431 len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date);
432 break;
433
434 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
435 len = strlen("modification-date=") +
436 strlen(param->pa_data.pa_modification_date);
437 break;
438
439 case MAILMIME_DISPOSITION_PARM_READ_DATE:
440 len = strlen("read-date=") + strlen(param->pa_data.pa_read_date);
441 break;
442
443 case MAILMIME_DISPOSITION_PARM_SIZE:
444 snprintf(sizestr, 20, "%lu", (unsigned long) param->pa_data.pa_size);
445 len = strlen("size=") + strlen(sizestr);
446 break;
447
448 case MAILMIME_DISPOSITION_PARM_PARAMETER:
449 len = strlen(param->pa_data.pa_parameter->pa_name) + 1 +
450 strlen(param->pa_data.pa_parameter->pa_value);
451 break;
452
453 default:
454 return MAILIMF_ERROR_INVAL;
455 }
456
457 if (* col > 1) {
458
459 if (* col + len > MAX_MAIL_COL) {
460 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
461 if (r != MAILIMF_NO_ERROR)
462 return r;
463#if 0
464 * col = 1;
465#endif
466 }
467 }
468
469 switch (param->pa_type) {
470 case MAILMIME_DISPOSITION_PARM_FILENAME:
471 r = mailimf_string_write_driver(do_write, data, col, "filename=", 9);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474
475 r = mailimf_quoted_string_write_driver(do_write, data, col,
476 param->pa_data.pa_filename, strlen(param->pa_data.pa_filename));
477 if (r != MAILIMF_NO_ERROR)
478 return r;
479 break;
480
481 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
482 r = mailimf_string_write_driver(do_write, data, col, "creation-date=", 14);
483 if (r != MAILIMF_NO_ERROR)
484 return r;
485
486 r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_creation_date,
487 strlen(param->pa_data.pa_creation_date));
488 if (r != MAILIMF_NO_ERROR)
489 return r;
490 break;
491
492 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
493 r = mailimf_string_write_driver(do_write, data, col, "modification-date=", 18);
494 if (r != MAILIMF_NO_ERROR)
495 return r;
496
497 r = mailimf_quoted_string_write_driver(do_write, data, col,
498 param->pa_data.pa_modification_date,
499 strlen(param->pa_data.pa_modification_date));
500 if (r != MAILIMF_NO_ERROR)
501 return r;
502 break;
503
504 case MAILMIME_DISPOSITION_PARM_READ_DATE:
505 r = mailimf_string_write_driver(do_write, data, col, "read-date=", 10);
506 if (r != MAILIMF_NO_ERROR)
507 return r;
508
509 r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_read_date,
510 strlen(param->pa_data.pa_read_date));
511 if (r != MAILIMF_NO_ERROR)
512 return r;
513 break;
514
515 case MAILMIME_DISPOSITION_PARM_SIZE:
516 r = mailimf_string_write_driver(do_write, data, col, "size=", 5);
517 if (r != MAILIMF_NO_ERROR)
518 return r;
519
520 r = mailimf_string_write_driver(do_write, data, col, sizestr, strlen(sizestr));
521 if (r != MAILIMF_NO_ERROR)
522 return r;
523 break;
524
525 case MAILMIME_DISPOSITION_PARM_PARAMETER:
526 r = mailmime_parameter_write_driver(do_write, data, col, param->pa_data.pa_parameter);
527 if (r != MAILIMF_NO_ERROR)
528 return r;
529 break;
530 }
531
532 return MAILIMF_NO_ERROR;
533}
534
535static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
536 struct mailmime_parameter * param)
537{
538 int r;
539
540 r = mailimf_string_write_driver(do_write, data, col, param->pa_name,
541 strlen(param->pa_name));
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544
545 r = mailimf_string_write_driver(do_write, data, col, "=", 1);
546 if (r != MAILIMF_NO_ERROR)
547 return r;
548
549 r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_value,
550 strlen(param->pa_value));
551 if (r != MAILIMF_NO_ERROR)
552 return r;
553
554 return MAILIMF_NO_ERROR;
555}
556
557int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
558 struct mailmime_content * content)
559{
560 clistiter * cur;
561 size_t len;
562 int r;
563
564 r = mailmime_type_write_driver(do_write, data, col, content->ct_type);
565 if (r != MAILIMF_NO_ERROR)
566 return r;
567
568 r = mailimf_string_write_driver(do_write, data, col, "/", 1);
569 if (r != MAILIMF_NO_ERROR)
570 return r;
571
572 r = mailimf_string_write_driver(do_write, data, col, content->ct_subtype,
573 strlen(content->ct_subtype));
574 if (r != MAILIMF_NO_ERROR)
575 return r;
576
577 if (content->ct_parameters != NULL) {
578 for(cur = clist_begin(content->ct_parameters) ;
579 cur != NULL ; cur = clist_next(cur)) {
580 struct mailmime_parameter * param;
581
582 param = cur->data;
583
584 r = mailimf_string_write_driver(do_write, data, col, "; ", 2);
585 if (r != MAILIMF_NO_ERROR)
586 return r;
587
588 len = strlen(param->pa_name) + 1 + strlen(param->pa_value);
589
590 if (* col > 1) {
591
592 if (* col + len > MAX_MAIL_COL) {
593 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
594 if (r != MAILIMF_NO_ERROR)
595 return r;
596#if 0
597 * col = 1;
598#endif
599 }
600 }
601
602 r = mailmime_parameter_write_driver(do_write, data, col, param);
603 if (r != MAILIMF_NO_ERROR)
604 return r;
605 }
606 }
607
608 return MAILIMF_NO_ERROR;
609}
610
611int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
612 struct mailmime_content * content)
613{
614 int r;
615
616 r = mailimf_string_write_driver(do_write, data, col, "Content-Type: ", 14);
617 if (r != MAILIMF_NO_ERROR)
618 return r;
619
620 r = mailmime_content_type_write_driver(do_write, data, col, content);
621 if (r != MAILIMF_NO_ERROR)
622 return r;
623
624 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
625 if (r != MAILIMF_NO_ERROR)
626 return r;
627
628 return MAILIMF_NO_ERROR;
629}
630
631static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
632 struct mailmime_type * type)
633{
634 int r;
635
636 switch (type->tp_type) {
637 case MAILMIME_TYPE_DISCRETE_TYPE:
638 r = mailmime_discrete_type_write_driver(do_write, data, col, type->tp_data.tp_discrete_type);
639 break;
640
641 case MAILMIME_TYPE_COMPOSITE_TYPE:
642 r = mailmime_composite_type_write_driver(do_write, data, col, type->tp_data.tp_composite_type);
643 break;
644
645 default:
646 r = MAILIMF_ERROR_INVAL;
647 break;
648 }
649
650 if (r != MAILIMF_NO_ERROR)
651 return r;
652
653 return MAILIMF_NO_ERROR;
654}
655
656static int
657mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
658 struct mailmime_discrete_type * discrete_type)
659{
660 int r;
661
662 switch (discrete_type->dt_type) {
663 case MAILMIME_DISCRETE_TYPE_TEXT:
664 r = mailimf_string_write_driver(do_write, data, col, "text", 4);
665 break;
666
667 case MAILMIME_DISCRETE_TYPE_IMAGE:
668 r = mailimf_string_write_driver(do_write, data, col, "image", 5);
669 break;
670
671 case MAILMIME_DISCRETE_TYPE_AUDIO:
672 r = mailimf_string_write_driver(do_write, data, col, "audio", 5);
673 break;
674
675 case MAILMIME_DISCRETE_TYPE_VIDEO:
676 r = mailimf_string_write_driver(do_write, data, col, "video", 5);
677 break;
678
679 case MAILMIME_DISCRETE_TYPE_APPLICATION:
680 r = mailimf_string_write_driver(do_write, data, col, "application", 11);
681 break;
682
683 case MAILMIME_DISCRETE_TYPE_EXTENSION:
684 r = mailimf_string_write_driver(do_write, data, col, discrete_type->dt_extension,
685 strlen(discrete_type->dt_extension));
686 break;
687
688 default:
689 r = MAILIMF_ERROR_INVAL;
690 break;
691 }
692
693 if (r != MAILIMF_NO_ERROR)
694 return r;
695
696 return MAILIMF_NO_ERROR;
697}
698
699static int
700mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
701 struct mailmime_composite_type * composite_type)
702{
703 int r;
704
705 switch (composite_type->ct_type) {
706 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
707 r = mailimf_string_write_driver(do_write, data, col, "message", 7);
708 break;
709
710 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
711 r = mailimf_string_write_driver(do_write, data, col, "multipart", 9);
712 break;
713
714 case MAILMIME_COMPOSITE_TYPE_EXTENSION:
715 r = mailimf_string_write_driver(do_write, data, col, composite_type->ct_token,
716 strlen(composite_type->ct_token));
717 break;
718
719 default:
720 r = MAILIMF_ERROR_INVAL;
721 break;
722 }
723
724 if (r != MAILIMF_NO_ERROR)
725 return r;
726
727 return MAILIMF_NO_ERROR;
728}
729
730
731
732
733/* ****************************************************************** */
734/* message */
735
736/*
737static int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
738 struct mailmime_data * data,
739 int is_text);
740*/
741
742static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding,
743 int istext,
744 const char * text, size_t size);
745
746/*
747static int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
748 char * text, size_t size);
749
750static int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
751 char * text, size_t size);
752*/
753
754static int mailmime_part_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
755 struct mailmime * build_info)
756{
757 clistiter * cur;
758 int first;
759 int r;
760 char * boundary;
761 int istext;
762
763 istext = TRUE;
764 boundary = NULL;
765
766 if (build_info->mm_content_type != NULL) {
767 if (build_info->mm_type == MAILMIME_MULTIPLE) {
768 boundary = mailmime_extract_boundary(build_info->mm_content_type);
769 if (boundary == NULL)
770 return MAILIMF_ERROR_INVAL;
771 }
772
773 if (build_info->mm_content_type->ct_type->tp_type ==
774 MAILMIME_TYPE_DISCRETE_TYPE) {
775 if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type !=
776 MAILMIME_DISCRETE_TYPE_TEXT)
777 istext = FALSE;
778 }
779 }
780
781 switch (build_info->mm_type) {
782 case MAILMIME_SINGLE:
783
784 /* 1-part body */
785
786 if (build_info->mm_data.mm_single != NULL) {
787 r = mailmime_data_write_driver(do_write, data, col, build_info->mm_data.mm_single, istext);
788 if (r != MAILIMF_NO_ERROR)
789 return r;
790 }
791
792 break;
793
794 case MAILMIME_MULTIPLE:
795
796 /* multi-part */
797
798
799 /* preamble */
800
801 if (build_info->mm_data.mm_multipart.mm_preamble != NULL) {
802 r = mailmime_data_write_driver(do_write, data, col,
803 build_info->mm_data.mm_multipart.mm_preamble, TRUE);
804 if (r != MAILIMF_NO_ERROR)
805 return r;
806
807 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
808 if (r != MAILIMF_NO_ERROR)
809 return r;
810#if 0
811 * col = 0;
812#endif
813 }
814
815 /* sub-parts */
816
817 first = TRUE;
818
819 for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ;
820 cur != NULL ; cur = clist_next(cur)) {
821 struct mailmime * subpart;
822
823 subpart = cur->data;
824
825 if (!first) {
826 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
827 if (r != MAILIMF_NO_ERROR)
828 return r;
829#if 0
830 * col = 0;
831#endif
832 }
833 else {
834 first = FALSE;
835 }
836
837 r = mailimf_string_write_driver(do_write, data, col, "--", 2);
838 if (r != MAILIMF_NO_ERROR)
839 return r;
840
841 r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary));
842 if (r != MAILIMF_NO_ERROR)
843 return r;
844
845 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
846 if (r != MAILIMF_NO_ERROR)
847 return r;
848#if 0
849 * col = 0;
850#endif
851
852 r = mailmime_sub_write_driver(do_write, data, col, subpart);
853 if (r != MAILIMF_NO_ERROR)
854 return r;
855 }
856
857 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
858 if (r != MAILIMF_NO_ERROR)
859 return r;
860#if 0
861 * col = 0;
862#endif
863
864 r = mailimf_string_write_driver(do_write, data, col, "--", 2);
865 if (r != MAILIMF_NO_ERROR)
866 return r;
867
868 r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary));
869 if (r != MAILIMF_NO_ERROR)
870 return r;
871
872 r = mailimf_string_write_driver(do_write, data, col, "--", 2);
873 if (r != MAILIMF_NO_ERROR)
874 return r;
875
876
877 /* epilogue */
878
879 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
880 if (r != MAILIMF_NO_ERROR)
881 return r;
882#if 0
883 * col = 0;
884#endif
885
886 if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) {
887 r = mailmime_data_write_driver(do_write, data, col,
888 build_info->mm_data.mm_multipart.mm_epilogue, TRUE);
889 if (r != MAILIMF_NO_ERROR)
890 return r;
891 }
892
893 break;
894
895 case MAILMIME_MESSAGE:
896
897 if (build_info->mm_data.mm_message.mm_fields != NULL) {
898 r = mailimf_fields_write_driver(do_write, data, col,
899 build_info->mm_data.mm_message.mm_fields);
900 if (r != MAILIMF_NO_ERROR)
901 return r;
902 }
903
904 if (build_info->mm_mime_fields != NULL) {
905 r = mailmime_fields_write_driver(do_write, data, col, build_info->mm_mime_fields);
906 if (r != MAILIMF_NO_ERROR)
907 return r;
908 }
909
910 /* encapsuled message */
911
912 if (build_info->mm_data.mm_message.mm_msg_mime != NULL) {
913 r = mailmime_sub_write_driver(do_write, data, col,
914 build_info->mm_data.mm_message.mm_msg_mime);
915 if (r != MAILIMF_NO_ERROR)
916 return r;
917 }
918 break;
919
920 }
921
922 return MAILIMF_NO_ERROR;
923}
924
925
926static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
927 struct mailmime * build_info)
928{
929 int r;
930
931#if 0
932 * col = 0;
933#endif
934 /* MIME field - Content-Type */
935
936 if (build_info->mm_content_type != NULL) {
937 r = mailmime_content_write_driver(do_write, data, col, build_info->mm_content_type);
938 if (r != MAILIMF_NO_ERROR)
939 return r;
940 }
941
942 /* other MIME fields */
943
944 if (build_info->mm_type != MAILMIME_MESSAGE) {
945 if (build_info->mm_mime_fields != NULL) {
946 r = mailmime_fields_write_driver(do_write, data, col, build_info->mm_mime_fields);
947 if (r != MAILIMF_NO_ERROR)
948 return r;
949 }
950 }
951
952 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
953 if (r != MAILIMF_NO_ERROR)
954 return r;
955#if 0
956 * col = 0;
957#endif
958
959 return mailmime_part_write_driver(do_write, data, col, build_info);
960}
961
962int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
963 struct mailmime * build_info)
964{
965 if (build_info->mm_parent != NULL)
966 return mailmime_sub_write_driver(do_write, data, col, build_info);
967 else
968 return mailmime_part_write_driver(do_write, data, col, build_info);
969}
970
971
972int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
973 struct mailmime_data * mime_data,
974 int istext)
975{
976 int fd;
977 int r;
978 char * text;
979 struct stat buf;
980 int res;
981
982 switch (mime_data->dt_type) {
983 case MAILMIME_DATA_TEXT:
984
985 if (mime_data->dt_encoded) {
986 r = mailimf_string_write_driver(do_write, data, col,
987 mime_data->dt_data.dt_text.dt_data,
988 mime_data->dt_data.dt_text.dt_length);
989 if (r != MAILIMF_NO_ERROR)
990 return r;
991 }
992 else {
993 r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext,
994 mime_data->dt_data.dt_text.dt_data,
995 mime_data->dt_data.dt_text.dt_length);
996 if (r != MAILIMF_NO_ERROR)
997 return r;
998 }
999
1000 break;
1001
1002 case MAILMIME_DATA_FILE:
1003 fd = open(mime_data->dt_data.dt_filename, O_RDONLY);
1004 if (fd < 0) {
1005 res = MAILIMF_ERROR_FILE;
1006 goto err;
1007 }
1008
1009 r = fstat(fd, &buf);
1010 if (r < 0) {
1011 res = MAILIMF_ERROR_FILE;
1012 goto close;
1013 }
1014
1015 if (buf.st_size != 0) {
1016 text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1017 if (text == MAP_FAILED) {
1018 res = MAILIMF_ERROR_FILE;
1019 goto close;
1020 }
1021
1022 if (mime_data->dt_encoded) {
1023 r = mailimf_string_write_driver(do_write, data, col, text, buf.st_size);
1024 if (r != MAILIMF_NO_ERROR) {
1025 res = r;
1026 goto unmap;
1027 }
1028 }
1029 else {
1030 r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext,
1031 text, buf.st_size);
1032 if (r != MAILIMF_NO_ERROR) {
1033 res = r;
1034 goto unmap;
1035 }
1036 }
1037
1038 munmap(text, buf.st_size);
1039 }
1040 close(fd);
1041
1042 if (r != MAILIMF_NO_ERROR)
1043 return r;
1044
1045 break;
1046
1047 unmap:
1048 munmap(text, buf.st_size);
1049 close:
1050 close(fd);
1051 err:
1052 return res;
1053 }
1054
1055 return MAILIMF_NO_ERROR;
1056}
1057
1058static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding,
1059 int istext,
1060 const char * text, size_t size)
1061{
1062 switch (encoding) {
1063 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
1064 return mailmime_quoted_printable_write_driver(do_write, data, col, istext, text, size);
1065 break;
1066
1067 case MAILMIME_MECHANISM_BASE64:
1068 return mailmime_base64_write_driver(do_write, data, col, text, size);
1069 break;
1070
1071 case MAILMIME_MECHANISM_7BIT:
1072 case MAILMIME_MECHANISM_8BIT:
1073 case MAILMIME_MECHANISM_BINARY:
1074 default:
1075 return mailimf_string_write_driver(do_write, data, col, text, size);
1076 }
1077}
1078
1079
1080static const char base64_encoding[] =
1081"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1082
1083#define BASE64_MAX_COL 76
1084
1085int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1086 const char * text, size_t size)
1087{
1088 int a;
1089 int b;
1090 int c;
1091 size_t remains;
1092 const char * p;
1093 size_t count;
1094 char ogroup[4];
1095 int r;
1096
1097 remains = size;
1098 p = text;
1099
1100 while (remains > 0) {
1101 switch (remains) {
1102 case 1:
1103 a = (unsigned char) p[0];
1104 b = 0;
1105 c = 0;
1106 count = 1;
1107 break;
1108 case 2:
1109 a = (unsigned char) p[0];
1110 b = (unsigned char) p[1];
1111 c = 0;
1112 count = 2;
1113 break;
1114 default:
1115 a = (unsigned char) p[0];
1116 b = (unsigned char) p[1];
1117 c = (unsigned char) p[2];
1118 count = 3;
1119 break;
1120 }
1121
1122 ogroup[0]= base64_encoding[a >> 2];
1123 ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)];
1124 ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)];
1125 ogroup[3]= base64_encoding[c & 0x3F];
1126
1127 switch (count) {
1128 case 1:
1129 ogroup[2]= '=';
1130 ogroup[3]= '=';
1131 break;
1132 case 2:
1133 ogroup[3]= '=';
1134 break;
1135 }
1136
1137 if (* col + 4 > BASE64_MAX_COL) {
1138 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1139 if (r != MAILIMF_NO_ERROR)
1140 return r;
1141#if 0
1142 * col = 0;
1143#endif
1144 }
1145
1146 r = mailimf_string_write_driver(do_write, data, col, ogroup, 4);
1147 if (r != MAILIMF_NO_ERROR)
1148 return r;
1149
1150 remains -= count;
1151 p += count;
1152 }
1153
1154 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1155
1156 return MAILIMF_NO_ERROR;
1157}
1158
1159#if 0
1160#define MAX_WRITE_SIZE 512
1161#endif
1162
1163enum {
1164 STATE_INIT,
1165 STATE_CR,
1166 STATE_SPACE,
1167 STATE_SPACE_CR,
1168};
1169
1170#if 0
1171static inline int write_try_buf(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1172 char ** pstart, size_t * plen)
1173{
1174 int r;
1175
1176 if (* plen >= MAX_WRITE_SIZE) {
1177 r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen);
1178 if (r != MAILIMF_NO_ERROR)
1179 return r;
1180 * plen = 0;
1181 }
1182
1183 return MAILIMF_NO_ERROR;
1184}
1185#endif
1186
1187static inline int write_remaining(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1188 const char ** pstart, size_t * plen)
1189{
1190 int r;
1191
1192 if (* plen > 0) {
1193 r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen);
1194 if (r != MAILIMF_NO_ERROR)
1195 return r;
1196 * plen = 0;
1197 }
1198
1199 return MAILIMF_NO_ERROR;
1200}
1201
1202
1203
1204#define QP_MAX_COL 72
1205
1206int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
1207 const char * text, size_t size)
1208{
1209 size_t i;
1210 const char * start;
1211 size_t len;
1212 char hexstr[6];
1213 int r;
1214 int state;
1215
1216 start = text;
1217 len = 0;
1218 state = STATE_INIT;
1219
1220 i = 0;
1221 while (i < size) {
1222 unsigned char ch;
1223
1224 if (* col + len > QP_MAX_COL) {
1225 r = write_remaining(do_write, data, col, &start, &len);
1226 if (r != MAILIMF_NO_ERROR)
1227 return r;
1228 start = text + i;
1229
1230 r = mailimf_string_write_driver(do_write, data, col, "=\r\n", 3);
1231 if (r != MAILIMF_NO_ERROR)
1232 return r;
1233 }
1234
1235 ch = text[i];
1236
1237 switch (state) {
1238
1239 case STATE_INIT:
1240 switch (ch) {
1241 case ' ':
1242 case '\t':
1243 state = STATE_SPACE;
1244 break;
1245
1246 case '\r':
1247 state = STATE_CR;
1248 break;
1249
1250 case '!':
1251 case '"':
1252 case '#':
1253 case '$':
1254 case '@':
1255 case '[':
1256 case '\\':
1257 case ']':
1258 case '^':
1259 case '`':
1260 case '{':
1261 case '|':
1262 case '}':
1263 case '~':
1264 case '=':
1265 case '?':
1266 case '_':
1267 case 'F': /* there is no more 'From' at the beginning of a line */
1268 r = write_remaining(do_write, data, col, &start, &len);
1269 if (r != MAILIMF_NO_ERROR)
1270 return r;
1271 start = text + i + 1;
1272
1273 snprintf(hexstr, 6, "=%02X", ch);
1274
1275 r = mailimf_string_write_driver(do_write, data, col, hexstr, 3);
1276 if (r != MAILIMF_NO_ERROR)
1277 return r;
1278 break;
1279
1280 default:
1281 if (istext && (ch == '\n')) {
1282 r = write_remaining(do_write, data, col, &start, &len);
1283 if (r != MAILIMF_NO_ERROR)
1284 return r;
1285 start = text + i + 1;
1286
1287 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1288 if (r != MAILIMF_NO_ERROR)
1289 return r;
1290 break;
1291 }
1292 else {
1293 if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) {
1294 len ++;
1295 }
1296 else {
1297 r = write_remaining(do_write, data, col, &start, &len);
1298 if (r != MAILIMF_NO_ERROR)
1299 return r;
1300 start = text + i + 1;
1301
1302 snprintf(hexstr, 6, "=%02X", ch);
1303
1304 r = mailimf_string_write_driver(do_write, data, col, hexstr, 3);
1305 if (r != MAILIMF_NO_ERROR)
1306 return r;
1307 }
1308 }
1309
1310 break;
1311 }
1312
1313 i ++;
1314 break;
1315
1316 case STATE_CR:
1317 switch (ch) {
1318 case '\n':
1319 r = write_remaining(do_write, data, col, &start, &len);
1320 if (r != MAILIMF_NO_ERROR)
1321 return r;
1322 start = text + i + 1;
1323 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1324 if (r != MAILIMF_NO_ERROR)
1325 return r;
1326 i ++;
1327 state = STATE_INIT;
1328 break;
1329
1330 default:
1331 r = write_remaining(do_write, data, col, &start, &len);
1332 if (r != MAILIMF_NO_ERROR)
1333 return r;
1334 start = text + i;
1335 snprintf(hexstr, 6, "=%02X", '\r');
1336 r = mailimf_string_write_driver(do_write, data, col, hexstr, 3);
1337 if (r != MAILIMF_NO_ERROR)
1338 return r;
1339 state = STATE_INIT;
1340 break;
1341 }
1342 break;
1343
1344 case STATE_SPACE:
1345 switch (ch) {
1346 case '\r':
1347 state = STATE_SPACE_CR;
1348 i ++;
1349 break;
1350
1351 case '\n':
1352 r = write_remaining(do_write, data, col, &start, &len);
1353 if (r != MAILIMF_NO_ERROR)
1354 return r;
1355 start = text + i + 1;
1356 snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]);
1357 r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr));
1358 if (r != MAILIMF_NO_ERROR)
1359 return r;
1360 state = STATE_INIT;
1361 i ++;
1362 break;
1363
1364 case ' ':
1365 case '\t':
1366 len ++;
1367 i ++;
1368 break;
1369
1370 default:
1371#if 0
1372 len += 2;
1373 state = STATE_INIT;
1374 i ++;
1375#endif
1376 len ++;
1377 state = STATE_INIT;
1378 break;
1379 }
1380
1381 break;
1382
1383 case STATE_SPACE_CR:
1384 switch (ch) {
1385 case '\n':
1386 r = write_remaining(do_write, data, col, &start, &len);
1387 if (r != MAILIMF_NO_ERROR)
1388 return r;
1389 start = text + i + 1;
1390 snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]);
1391 r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr));
1392 if (r != MAILIMF_NO_ERROR)
1393 return r;
1394 state = STATE_INIT;
1395 i ++;
1396 break;
1397
1398 default:
1399 r = write_remaining(do_write, data, col, &start, &len);
1400 if (r != MAILIMF_NO_ERROR)
1401 return r;
1402 start = text + i + 1;
1403 snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r');
1404 r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr));
1405 if (r != MAILIMF_NO_ERROR)
1406 return r;
1407 state = STATE_INIT;
1408 break;
1409 }
1410
1411 break;
1412 }
1413 }
1414
1415 return MAILIMF_NO_ERROR;
1416}
diff --git a/libetpan/src/low-level/mime/mailmime_write_generic.h b/libetpan/src/low-level/mime/mailmime_write_generic.h
new file mode 100644
index 0000000..0d9a725
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_generic.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_GENERIC_H
37
38#define MAILMIME_WRITE_GENERIC_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailmime_data * mime_data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write_mem.c b/libetpan/src/low-level/mime/mailmime_write_mem.c
new file mode 100644
index 0000000..4b41d34
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_mem.c
@@ -0,0 +1,106 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_write_mem.h"
37
38#include <stdlib.h>
39#include <string.h>
40#include <time.h>
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include <sys/mman.h>
46
47#include "mailmime_content.h"
48#include "mailmime_types_helper.h"
49#include "mailmime_write_generic.h"
50
51static int do_write(void * data, const char * str, size_t length)
52{
53 MMAPString * f;
54
55 f = data;
56
57 if (mmap_string_append_len(f, str, length) == NULL)
58 return 0;
59 else
60 return length;
61}
62
63int mailmime_fields_write_mem(MMAPString * f, int * col,
64 struct mailmime_fields * fields)
65{
66 return mailmime_fields_write_driver(do_write, f, col, fields);
67}
68
69int mailmime_content_write_mem(MMAPString * f, int * col,
70 struct mailmime_content * content)
71{
72 return mailmime_content_write_driver(do_write, f, col, content);
73}
74
75int mailmime_content_type_write_mem(MMAPString * f, int * col,
76 struct mailmime_content * content)
77{
78 return mailmime_content_type_write_driver(do_write, f, col, content);
79}
80
81int mailmime_write_mem(MMAPString * f, int * col,
82 struct mailmime * build_info)
83{
84 return mailmime_write_driver(do_write, f, col, build_info);
85}
86
87int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext,
88 const char * text, size_t size)
89{
90 return mailmime_quoted_printable_write_driver(do_write, f, col,
91 istext, text, size);
92}
93
94int mailmime_base64_write_mem(MMAPString * f, int * col,
95 const char * text, size_t size)
96{
97 return mailmime_base64_write_driver(do_write, f, col, text, size);
98}
99
100int mailmime_data_write_mem(MMAPString * f, int * col,
101 struct mailmime_data * data,
102 int istext)
103{
104 return mailmime_data_write_driver(do_write, f, col, data, istext);
105}
106
diff --git a/libetpan/src/low-level/mime/mailmime_write_mem.h b/libetpan/src/low-level/mime/mailmime_write_mem.h
new file mode 100644
index 0000000..f86d129
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_mem.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILMIME_WRITE_MEM_H
37
38#define MAILMIME_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <libetpan/mmapstring.h>
46
47int mailmime_fields_write_mem(MMAPString * f, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_mem(MMAPString * f, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_mem(MMAPString * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_mem(MMAPString * f, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_mem(MMAPString * f, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_mem(MMAPString * f, int * col,
66 struct mailmime_data * data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/src/low-level/nntp/newsnntp.c b/libetpan/src/low-level/nntp/newsnntp.c
new file mode 100644
index 0000000..bf2312c
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp.c
@@ -0,0 +1,2486 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "newsnntp.h"
37
38
39#include <unistd.h>
40#include <stdio.h>
41#include <netinet/in.h>
42#include <netdb.h>
43#include <string.h>
44#include <stdlib.h>
45#include <time.h>
46
47#include "connect.h"
48#include "mail.h"
49#include "clist.h"
50
51/*
52 NNTP Protocol
53
54 RFC 977
55 RFC 2980
56
57 TODO :
58
59 XPAT header range|<message-id> pat [pat...]
60
61
62 */
63
64
65
66
67#define NNTP_STRING_SIZE 513
68
69
70
71static char * read_line(newsnntp * f);
72static char * read_multiline(newsnntp * f, size_t size,
73 MMAPString * multiline_buffer);
74static int parse_response(newsnntp * f, char * response);
75
76static int send_command(newsnntp * f, char * command);
77
78newsnntp * newsnntp_new(size_t progr_rate, progress_function * progr_fun)
79{
80 newsnntp * f;
81
82 f = malloc(sizeof(* f));
83 if (f == NULL)
84 goto err;
85
86 f->nntp_stream = NULL;
87 f->nntp_readonly = FALSE;
88
89 f->nntp_progr_rate = progr_rate;
90 f->nntp_progr_fun = progr_fun;
91
92 f->nntp_stream_buffer = mmap_string_new("");
93 if (f->nntp_stream_buffer == NULL)
94 goto free_f;
95
96 f->nntp_response_buffer = mmap_string_new("");
97 if (f->nntp_response_buffer == NULL)
98 goto free_stream_buffer;
99
100 return f;
101
102 free_stream_buffer:
103 mmap_string_free(f->nntp_stream_buffer);
104 free_f:
105 free(f);
106 err:
107 return NULL;
108}
109
110void newsnntp_free(newsnntp * f)
111{
112 if (f->nntp_stream)
113 newsnntp_quit(f);
114
115 mmap_string_free(f->nntp_response_buffer);
116 mmap_string_free(f->nntp_stream_buffer);
117
118 free(f);
119}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136int newsnntp_quit(newsnntp * f)
137{
138 char command[NNTP_STRING_SIZE];
139 char * response;
140 int r;
141 int res;
142
143 if (f->nntp_stream == NULL)
144 return NEWSNNTP_ERROR_BAD_STATE;
145
146 snprintf(command, NNTP_STRING_SIZE, "QUIT\r\n");
147 r = send_command(f, command);
148 if (r == -1) {
149 res = NEWSNNTP_ERROR_STREAM;
150 goto close;
151 }
152
153 response = read_line(f);
154 if (response == NULL) {
155 res = NEWSNNTP_ERROR_STREAM;
156 goto close;
157 }
158
159 parse_response(f, response);
160
161 res = NEWSNNTP_NO_ERROR;
162
163 close:
164
165 mailstream_close(f->nntp_stream);
166
167 f->nntp_stream = NULL;
168
169 return res;
170}
171
172int newsnntp_connect(newsnntp * f, mailstream * s)
173{
174 char * response;
175 int r;
176
177 if (f->nntp_stream != NULL)
178 return NEWSNNTP_ERROR_BAD_STATE;
179
180 f->nntp_stream = s;
181
182 response = read_line(f);
183 if (response == NULL)
184 return NEWSNNTP_ERROR_STREAM;
185
186 r = parse_response(f, response);
187
188 switch (r) {
189 case 200:
190 f->nntp_readonly = FALSE;
191 return NEWSNNTP_NO_ERROR;
192
193 case 201:
194 f->nntp_readonly = TRUE;
195 return NEWSNNTP_NO_ERROR;
196
197 default:
198 f->nntp_stream = NULL;
199 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
200 }
201}
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222/*
223static struct newsnntp_xover_resp_item * get_xover_info(newsnntp * f,
224 guint32 article);
225*/
226
227static void newsnntp_multiline_response_free(char * str)
228{
229 mmap_string_unref(str);
230}
231
232void newsnntp_head_free(char * str)
233{
234 newsnntp_multiline_response_free(str);
235}
236
237void newsnntp_article_free(char * str)
238{
239 newsnntp_multiline_response_free(str);
240}
241
242void newsnntp_body_free(char * str)
243{
244 newsnntp_multiline_response_free(str);
245}
246
247/* ******************** HEADER ******************************** */
248
249/*
250 message content in (* result) is still there until the
251 next retrieve or top operation on the mailpop3 structure
252*/
253
254static int newsnntp_get_content(newsnntp * f, char ** result,
255 size_t * result_len)
256{
257 int r;
258 char * response;
259 MMAPString * buffer;
260 char * result_multiline;
261
262 response = read_line(f);
263 if (response == NULL)
264 return NEWSNNTP_ERROR_STREAM;
265
266 r = parse_response(f, response);
267
268 switch (r) {
269 case 480:
270 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
271
272 case 381:
273 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
274
275 case 220:
276 case 221:
277 case 222:
278 case 223:
279 buffer = mmap_string_new("");
280 if (buffer == NULL)
281 return NEWSNNTP_ERROR_MEMORY;
282
283 result_multiline = read_multiline(f, 0, buffer);
284 if (result_multiline == NULL) {
285 mmap_string_free(buffer);
286 return NEWSNNTP_ERROR_MEMORY;
287 }
288 else {
289 r = mmap_string_ref(buffer);
290 if (r < 0) {
291 mmap_string_free(buffer);
292 return NEWSNNTP_ERROR_MEMORY;
293 }
294
295 * result = result_multiline;
296 * result_len = buffer->len;
297 return NEWSNNTP_NO_ERROR;
298 }
299
300 case 412:
301 return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED;
302
303 case 420:
304 return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED;
305
306 case 423:
307 return NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER;
308
309 case 430:
310 return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND;
311
312 default:
313 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
314 }
315}
316
317int newsnntp_head(newsnntp * f, uint32_t index, char ** result,
318 size_t * result_len)
319{
320 char command[NNTP_STRING_SIZE];
321 int r;
322
323 snprintf(command, NNTP_STRING_SIZE, "HEAD %i\r\n", index);
324 r = send_command(f, command);
325 if (r == -1)
326 return NEWSNNTP_ERROR_STREAM;
327
328 return newsnntp_get_content(f, result, result_len);
329}
330
331/* ******************** ARTICLE ******************************** */
332
333int newsnntp_article(newsnntp * f, uint32_t index, char ** result,
334 size_t * result_len)
335{
336 char command[NNTP_STRING_SIZE];
337 int r;
338
339 snprintf(command, NNTP_STRING_SIZE, "ARTICLE %i\r\n", index);
340 r = send_command(f, command);
341 if (r == -1)
342 return NEWSNNTP_ERROR_STREAM;
343
344 return newsnntp_get_content(f, result, result_len);
345}
346
347/* ******************** BODY ******************************** */
348
349int newsnntp_body(newsnntp * f, uint32_t index, char ** result,
350 size_t * result_len)
351{
352 char command[NNTP_STRING_SIZE];
353 int r;
354
355 snprintf(command, NNTP_STRING_SIZE, "BODY %i\r\n", index);
356 r = send_command(f, command);
357 if (r == -1)
358 return NEWSNNTP_ERROR_STREAM;
359
360 return newsnntp_get_content(f, result, result_len);
361}
362
363/* ******************** GROUP ******************************** */
364
365static struct newsnntp_group_info *
366group_info_init(char * name, uint32_t first, uint32_t last, uint32_t count,
367 char type)
368{
369 struct newsnntp_group_info * n;
370
371 n = malloc(sizeof(* n));
372
373 if (n == NULL)
374 return NULL;
375
376 n->grp_name = strdup(name);
377 if (n->grp_name == NULL) {
378 free(n);
379 return NULL;
380 }
381
382 n->grp_first = first;
383 n->grp_last = last;
384 n->grp_count = count;
385 n->grp_type = type;
386
387 return n;
388}
389
390static void group_info_free(struct newsnntp_group_info * n)
391{
392 if (n->grp_name)
393 free(n->grp_name);
394 free(n);
395}
396
397static void group_info_list_free(clist * l)
398{
399 clist_foreach(l, (clist_func) group_info_free, NULL);
400 clist_free(l);
401}
402
403static int parse_group_info(char * response,
404 struct newsnntp_group_info ** info);
405
406int newsnntp_group(newsnntp * f, const char * groupname,
407 struct newsnntp_group_info ** info)
408{
409 char command[NNTP_STRING_SIZE];
410 int r;
411 char * response;
412
413 snprintf(command, NNTP_STRING_SIZE, "GROUP %s\r\n", groupname);
414 r = send_command(f, command);
415 if (r == -1)
416 return NEWSNNTP_ERROR_STREAM;
417
418 response = read_line(f);
419 if (response == NULL)
420 return NEWSNNTP_ERROR_STREAM;
421
422 r = parse_response(f, response);
423
424 switch (r) {
425 case 480:
426 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
427
428 case 381:
429 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
430
431 case 211:
432 if (!parse_group_info(f->nntp_response, info))
433 return NEWSNNTP_ERROR_INVALID_RESPONSE;
434 return NEWSNNTP_NO_ERROR;
435
436 case 411:
437 return NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP;
438
439 default:
440 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
441 }
442}
443
444void newsnntp_group_free(struct newsnntp_group_info * info)
445{
446 group_info_free(info);
447}
448
449/* ******************** LIST ******************************** */
450
451static clist * read_groups_list(newsnntp * f);
452
453int newsnntp_list(newsnntp * f, clist ** result)
454{
455 char command[NNTP_STRING_SIZE];
456 int r;
457 char * response;
458
459 snprintf(command, NNTP_STRING_SIZE, "LIST\r\n");
460 r = send_command(f, command);
461 if (r == -1)
462 return NEWSNNTP_ERROR_STREAM;
463
464 response = read_line(f);
465 if (response == NULL)
466 return NEWSNNTP_ERROR_STREAM;
467
468 r = parse_response(f, response);
469
470 switch (r) {
471 case 480:
472 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
473
474 case 381:
475 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
476
477 case 215:
478 * result = read_groups_list(f);
479 return NEWSNNTP_NO_ERROR;
480
481 default:
482 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
483 }
484}
485
486void newsnntp_list_free(clist * l)
487{
488 group_info_list_free(l);
489}
490
491/* ******************** POST ******************************** */
492
493static void send_data(newsnntp * f, const char * message, uint32_t size)
494{
495 mailstream_send_data(f->nntp_stream, message, size,
496 f->nntp_progr_rate, f->nntp_progr_fun);
497}
498
499
500int newsnntp_post(newsnntp * f, const char * message, size_t size)
501{
502 char command[NNTP_STRING_SIZE];
503 int r;
504 char * response;
505
506 snprintf(command, NNTP_STRING_SIZE, "POST\r\n");
507 r = send_command(f, command);
508 if (r == -1)
509 return NEWSNNTP_ERROR_STREAM;
510
511 response = read_line(f);
512 if (response == NULL)
513 return NEWSNNTP_ERROR_STREAM;
514
515 r = parse_response(f, response);
516
517 switch (r) {
518 case 480:
519 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
520
521 case 381:
522 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
523
524 case 340:
525 break;
526
527 case 440:
528 return NEWSNNTP_ERROR_POSTING_NOT_ALLOWED;
529
530 default:
531 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
532 }
533
534 send_data(f, message, size);
535
536 response = read_line(f);
537 if (response == NULL)
538 return NEWSNNTP_ERROR_STREAM;
539
540 r = parse_response(f, response);
541
542 switch (r) {
543 case 480:
544 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
545
546 case 381:
547 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
548
549 case 240:
550 return NEWSNNTP_NO_ERROR;
551 return 1;
552
553 case 441:
554 return NEWSNNTP_ERROR_POSTING_FAILED;
555
556 default:
557 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
558 }
559}
560
561
562/* ******************** AUTHINFO ******************************** */
563
564int newsnntp_authinfo_username(newsnntp * f, const char * username)
565{
566 char command[NNTP_STRING_SIZE];
567 int r;
568 char * response;
569
570 snprintf(command, NNTP_STRING_SIZE, "AUTHINFO USER %s\r\n", username);
571 r = send_command(f, command);
572 if (r == -1)
573 return NEWSNNTP_ERROR_STREAM;
574
575 response = read_line(f);
576 if (response == NULL)
577 return NEWSNNTP_ERROR_STREAM;
578
579 r = parse_response(f, response);
580
581 switch (r) {
582 case 480:
583 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
584
585 case 482:
586 return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED;
587
588 case 381:
589 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
590
591 case 281:
592 return NEWSNNTP_NO_ERROR;
593
594 default:
595 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
596 }
597}
598
599int newsnntp_authinfo_password(newsnntp * f, const char * password)
600{
601 char command[NNTP_STRING_SIZE];
602 int r;
603 char * response;
604
605 snprintf(command, NNTP_STRING_SIZE, "AUTHINFO PASS %s\r\n", password);
606 r = send_command(f, command);
607 if (r == -1)
608 return NEWSNNTP_ERROR_STREAM;
609
610 response = read_line(f);
611 if (response == NULL)
612 return NEWSNNTP_ERROR_STREAM;
613
614 r = parse_response(f, response);
615
616 switch (r) {
617 case 480:
618 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
619
620 case 482:
621 return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED;
622
623 case 381:
624 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
625
626 case 281:
627 return NEWSNNTP_NO_ERROR;
628
629 default:
630 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
631 }
632}
633
634/* ******************** LIST OVERVIEW.FMT ******************************** */
635
636static clist * read_headers_list(newsnntp * f);
637
638static void headers_list_free(clist * l)
639{
640 clist_foreach(l, (clist_func) free, NULL);
641 clist_free(l);
642}
643
644int newsnntp_list_overview_fmt(newsnntp * f, clist ** result)
645{
646 char command[NNTP_STRING_SIZE];
647 int r;
648 char * response;
649
650 snprintf(command, NNTP_STRING_SIZE, "LIST OVERVIEW.FMT\r\n");
651 r = send_command(f, command);
652 if (r == -1)
653 return NEWSNNTP_ERROR_STREAM;
654
655 response = read_line(f);
656 if (response == NULL)
657 return NEWSNNTP_ERROR_STREAM;
658
659 r = parse_response(f, response);
660
661 switch (r) {
662 case 480:
663 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
664
665 case 381:
666 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
667
668 case 215:
669 * result = read_headers_list(f);
670 return NEWSNNTP_NO_ERROR;
671
672 case 503:
673 return NEWSNNTP_ERROR_PROGRAM_ERROR;
674
675 default:
676 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
677 }
678}
679
680void newsnntp_list_overview_fmt_free(clist * l)
681{
682 headers_list_free(l);
683}
684
685
686
687
688
689
690/* ******************** LIST ACTIVE ******************************** */
691
692int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result)
693{
694 char command[NNTP_STRING_SIZE];
695 int r;
696 char * response;
697
698 if (wildcard != NULL)
699 snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE %s\r\n", wildcard);
700 else
701 snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE\r\n");
702 r = send_command(f, command);
703 if (r == -1)
704 return NEWSNNTP_ERROR_STREAM;
705
706 response = read_line(f);
707 if (response == NULL)
708 return NEWSNNTP_ERROR_STREAM;
709
710 r = parse_response(f, response);
711
712 switch (r) {
713 case 480:
714 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
715
716 case 381:
717 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
718
719 case 215:
720 * result = read_groups_list(f);
721 return NEWSNNTP_NO_ERROR;
722
723 default:
724 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
725 }
726}
727
728void newsnntp_list_active_free(clist * l)
729{
730 group_info_list_free(l);
731}
732
733
734
735
736
737
738/* ******************** LIST ACTIVE.TIMES ******************************** */
739
740static struct newsnntp_group_time *
741group_time_new(char * group_name, time_t date, char * email)
742{
743 struct newsnntp_group_time * n;
744
745 n = malloc(sizeof(* n));
746
747 if (n == NULL)
748 return NULL;
749
750 n->grp_name = strdup(group_name);
751 if (n->grp_name == NULL) {
752 free(n);
753 return NULL;
754 }
755
756 n->grp_email = strdup(email);
757 if (n->grp_email == NULL) {
758 free(n->grp_name);
759 free(n);
760 return NULL;
761 }
762
763 n->grp_date = date;
764
765 return n;
766}
767
768static void group_time_free(struct newsnntp_group_time * n)
769{
770 if (n->grp_name)
771 free(n->grp_name);
772 if (n->grp_email)
773 free(n->grp_email);
774 free(n);
775}
776
777static void group_time_list_free(clist * l)
778{
779 clist_foreach(l, (clist_func) group_time_free, NULL);
780 clist_free(l);
781}
782
783
784
785
786
787
788
789static clist * read_group_time_list(newsnntp * f);
790
791
792int newsnntp_list_active_times(newsnntp * f, clist ** result)
793{
794 char command[NNTP_STRING_SIZE];
795 int r;
796 char * response;
797
798 snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE.TIMES\r\n");
799 r = send_command(f, command);
800 if (r == -1)
801 return NEWSNNTP_ERROR_STREAM;
802
803 response = read_line(f);
804 if (response == NULL)
805 return NEWSNNTP_ERROR_STREAM;
806
807 r = parse_response(f, response);
808
809 switch (r) {
810 case 480:
811 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
812
813 case 381:
814 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
815
816 case 215:
817 * result = read_group_time_list(f);
818 return NEWSNNTP_NO_ERROR;
819
820 case 503:
821 return NEWSNNTP_ERROR_PROGRAM_ERROR;
822
823 default:
824 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
825 }
826}
827
828void newsnntp_list_active_times_free(clist * l)
829{
830 group_time_list_free(l);
831}
832
833
834
835
836
837
838
839
840/* ********************** LIST DISTRIBUTION ***************************** */
841
842static struct newsnntp_distrib_value_meaning *
843distrib_value_meaning_new(char * value, char * meaning)
844{
845 struct newsnntp_distrib_value_meaning * n;
846
847 n = malloc(sizeof(* n));
848
849 if (n == NULL)
850 return NULL;
851
852 n->dst_value = strdup(value);
853 if (n->dst_value == NULL) {
854 free(n);
855 return NULL;
856 }
857
858 n->dst_meaning = strdup(meaning);
859 if (n->dst_meaning == NULL) {
860 free(n->dst_value);
861 free(n);
862 return NULL;
863 }
864
865 return n;
866}
867
868
869static void
870distrib_value_meaning_free(struct newsnntp_distrib_value_meaning * n)
871{
872 if (n->dst_value)
873 free(n->dst_value);
874 if (n->dst_meaning)
875 free(n->dst_meaning);
876 free(n);
877}
878
879static void distrib_value_meaning_list_free(clist * l)
880{
881 clist_foreach(l, (clist_func) distrib_value_meaning_free, NULL);
882 clist_free(l);
883}
884
885static clist * read_distrib_value_meaning_list(newsnntp * f);
886
887
888int newsnntp_list_distribution(newsnntp * f, clist ** result)
889{
890 char command[NNTP_STRING_SIZE];
891 int r;
892 char * response;
893
894 snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIBUTION\r\n");
895 r = send_command(f, command);
896 if (r == -1)
897 return NEWSNNTP_ERROR_STREAM;
898
899 response = read_line(f);
900 if (response == NULL)
901 return NEWSNNTP_ERROR_STREAM;
902
903 r = parse_response(f, response);
904
905 switch (r) {
906 case 480:
907 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
908
909 case 381:
910 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
911
912 case 215:
913 * result = read_distrib_value_meaning_list(f);
914 return NEWSNNTP_NO_ERROR;
915
916 case 503:
917 return NEWSNNTP_ERROR_PROGRAM_ERROR;
918
919 default:
920 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
921 }
922}
923
924
925void newsnntp_list_distribution_free(clist * l)
926{
927 distrib_value_meaning_list_free(l);
928}
929
930
931
932
933
934
935
936
937
938
939
940/* ********************** LIST DISTRIB.PATS ***************************** */
941
942static struct newsnntp_distrib_default_value *
943distrib_default_value_new(uint32_t weight, char * group_pattern, char * value)
944{
945 struct newsnntp_distrib_default_value * n;
946
947 n = malloc(sizeof(* n));
948 if (n == NULL)
949 return NULL;
950
951 n->dst_group_pattern = strdup(group_pattern);
952 if (n->dst_group_pattern == NULL) {
953 free(n);
954 return NULL;
955 }
956
957 n->dst_value = strdup(value);
958 if (n->dst_value == NULL) {
959 free(n->dst_group_pattern);
960 free(n);
961 return NULL;
962 }
963
964 n->dst_weight = weight;
965
966 return n;
967}
968
969static void
970distrib_default_value_free(struct newsnntp_distrib_default_value * n)
971{
972 if (n->dst_group_pattern)
973 free(n->dst_group_pattern);
974 if (n->dst_value)
975 free(n->dst_value);
976 free(n);
977}
978
979static void distrib_default_value_list_free(clist * l)
980{
981 clist_foreach(l, (clist_func) distrib_default_value_free, NULL);
982 clist_free(l);
983}
984
985static clist * read_distrib_default_value_list(newsnntp * f);
986
987int newsnntp_list_distrib_pats(newsnntp * f, clist ** result)
988{
989 char command[NNTP_STRING_SIZE];
990 int r;
991 char * response;
992
993 snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIB.PATS\r\n");
994 r = send_command(f, command);
995 if (r == -1)
996 return NEWSNNTP_ERROR_STREAM;
997
998 response = read_line(f);
999 if (response == NULL)
1000 return NEWSNNTP_ERROR_STREAM;
1001
1002 r = parse_response(f, response);
1003
1004 switch (r) {
1005 case 480:
1006 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1007
1008 case 381:
1009 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1010
1011 case 215:
1012 * result = read_distrib_default_value_list(f);
1013 return NEWSNNTP_NO_ERROR;
1014
1015 case 503:
1016 return NEWSNNTP_ERROR_PROGRAM_ERROR;
1017
1018 default:
1019 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1020 }
1021}
1022
1023void newsnntp_list_distrib_pats_free(clist * l)
1024{
1025 distrib_default_value_list_free(l);
1026}
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039/* ********************** LIST NEWSGROUPS ***************************** */
1040
1041static struct newsnntp_group_description *
1042group_description_new(char * group_name, char * description)
1043{
1044 struct newsnntp_group_description * n;
1045
1046 n = malloc(sizeof(* n));
1047 if (n == NULL)
1048 return NULL;
1049
1050 n->grp_name = strdup(group_name);
1051 if (n->grp_name == NULL) {
1052 free(n);
1053 return NULL;
1054 }
1055
1056 n->grp_description = strdup(description);
1057 if (n->grp_description == NULL) {
1058 free(n->grp_name);
1059 free(n);
1060 return NULL;
1061 }
1062
1063 return n;
1064}
1065
1066static void group_description_free(struct newsnntp_group_description * n)
1067{
1068 if (n->grp_name)
1069 free(n->grp_name);
1070 if (n->grp_description)
1071 free(n->grp_description);
1072 free(n);
1073}
1074
1075static void group_description_list_free(clist * l)
1076{
1077 clist_foreach(l, (clist_func) group_description_free, NULL);
1078 clist_free(l);
1079}
1080
1081static clist * read_group_description_list(newsnntp * f);
1082
1083int newsnntp_list_newsgroups(newsnntp * f, const char * pattern,
1084 clist ** result)
1085{
1086 char command[NNTP_STRING_SIZE];
1087 int r;
1088 char * response;
1089
1090 if (pattern)
1091 snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS %s\r\n", pattern);
1092 else
1093 snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS\r\n");
1094
1095 r = send_command(f, command);
1096 if (r == -1)
1097 return NEWSNNTP_ERROR_STREAM;
1098
1099 response = read_line(f);
1100 if (response == NULL)
1101 return NEWSNNTP_ERROR_STREAM;
1102
1103 r = parse_response(f, response);
1104
1105 switch (r) {
1106 case 480:
1107 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1108
1109 case 381:
1110 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1111
1112 case 215:
1113 * result = read_group_description_list(f);
1114 return NEWSNNTP_NO_ERROR;
1115
1116 case 503:
1117 return NEWSNNTP_ERROR_PROGRAM_ERROR;
1118
1119 default:
1120 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1121 }
1122}
1123
1124void newsnntp_list_newsgroups_free(clist * l)
1125{
1126 group_description_list_free(l);
1127}
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140/* ******************** LIST SUBSCRIPTIONS ******************************** */
1141
1142static void subscriptions_list_free(clist * l)
1143{
1144 clist_foreach(l, (clist_func) free, NULL);
1145 clist_free(l);
1146}
1147
1148static clist * read_subscriptions_list(newsnntp * f);
1149
1150int newsnntp_list_subscriptions(newsnntp * f, clist ** result)
1151{
1152 char command[NNTP_STRING_SIZE];
1153 int r;
1154 char * response;
1155
1156 snprintf(command, NNTP_STRING_SIZE, "LIST SUBSCRIPTIONS\r\n");
1157 r = send_command(f, command);
1158 if (r == -1)
1159 return NEWSNNTP_ERROR_STREAM;
1160
1161 response = read_line(f);
1162 if (response == NULL)
1163 return NEWSNNTP_ERROR_STREAM;
1164
1165 r = parse_response(f, response);
1166
1167 switch (r) {
1168 case 480:
1169 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1170
1171 case 381:
1172 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1173
1174 case 215:
1175 * result = read_subscriptions_list(f);
1176 return NEWSNNTP_NO_ERROR;
1177
1178 case 503:
1179 return NEWSNNTP_ERROR_PROGRAM_ERROR;
1180
1181 default:
1182 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1183 }
1184}
1185
1186void newsnntp_list_subscriptions_free(clist * l)
1187{
1188 subscriptions_list_free(l);
1189}
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202/* ******************** LISTGROUP ******************************** */
1203
1204static void articles_list_free(clist * l)
1205{
1206 clist_foreach(l, (clist_func) free, NULL);
1207 clist_free(l);
1208}
1209
1210static clist * read_articles_list(newsnntp * f);
1211
1212int newsnntp_listgroup(newsnntp * f, const char * group_name,
1213 clist ** result)
1214{
1215 char command[NNTP_STRING_SIZE];
1216 int r;
1217 char * response;
1218
1219 if (group_name)
1220 snprintf(command, NNTP_STRING_SIZE, "LISTGROUP %s\r\n", group_name);
1221 else
1222 snprintf(command, NNTP_STRING_SIZE, "LISTGROUP\r\n");
1223 r = send_command(f, command);
1224 if (r == -1)
1225 return NEWSNNTP_ERROR_STREAM;
1226
1227 response = read_line(f);
1228 if (response == NULL)
1229 return NEWSNNTP_ERROR_STREAM;
1230
1231 r = parse_response(f, response);
1232
1233 switch (r) {
1234 case 480:
1235 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1236
1237 case 381:
1238 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1239
1240 case 211:
1241 * result = read_articles_list(f);
1242 return NEWSNNTP_NO_ERROR;
1243
1244 case 412:
1245 return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED;
1246
1247 case 502:
1248 return NEWSNNTP_ERROR_NO_PERMISSION;
1249
1250 default:
1251 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1252 }
1253}
1254
1255void newsnntp_listgroup_free(clist * l)
1256{
1257 articles_list_free(l);
1258}
1259
1260
1261
1262
1263
1264
1265
1266/* ********************** MODE READER ***************************** */
1267
1268int newsnntp_mode_reader(newsnntp * f)
1269{
1270 char command[NNTP_STRING_SIZE];
1271 char * response;
1272 int r;
1273
1274 snprintf(command, NNTP_STRING_SIZE, "MODE READER\r\n");
1275
1276 r = send_command(f, command);
1277 if (r == -1)
1278 return NEWSNNTP_ERROR_STREAM;
1279
1280 response = read_line(f);
1281 if (response == NULL)
1282 return NEWSNNTP_ERROR_STREAM;
1283
1284 r = parse_response(f, response);
1285 switch (r) {
1286 case 480:
1287 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1288
1289 case 381:
1290 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1291
1292 case 200:
1293 return NEWSNNTP_NO_ERROR;
1294
1295 default:
1296 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1297 }
1298}
1299
1300/* ********************** DATE ***************************** */
1301
1302#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}}
1303
1304int newsnntp_date(newsnntp * f, struct tm * tm)
1305{
1306 char command[NNTP_STRING_SIZE];
1307 int r;
1308 char * response;
1309 char year[5];
1310 char month[3];
1311 char day[3];
1312 char hour[3];
1313 char minute[3];
1314 char second[3];
1315
1316 snprintf(command, NNTP_STRING_SIZE, "DATE\r\n");
1317 r = send_command(f, command);
1318 if (r == -1)
1319 return NEWSNNTP_ERROR_STREAM;
1320
1321 response = read_line(f);
1322 if (response == NULL)
1323 return NEWSNNTP_ERROR_STREAM;
1324
1325 r = parse_response(f, response);
1326
1327 switch (r) {
1328 case 111:
1329 strfcpy(year, f->nntp_response, 4);
1330 strfcpy(month, f->nntp_response + 4, 2);
1331 strfcpy(day, f->nntp_response + 6, 2);
1332 strfcpy(hour, f->nntp_response + 8, 2);
1333 strfcpy(minute, f->nntp_response + 10, 2);
1334 strfcpy(second, f->nntp_response + 12, 2);
1335
1336 tm->tm_year = atoi(year);
1337 tm->tm_mon = atoi(month);
1338 tm->tm_mday = atoi(day);
1339 tm->tm_hour = atoi(hour);
1340 tm->tm_min = atoi(minute);
1341 tm->tm_sec = atoi(second);
1342
1343 return NEWSNNTP_NO_ERROR;
1344
1345 default:
1346 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1347 }
1348}
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358/* ********************** XHDR ***************************** */
1359
1360static struct newsnntp_xhdr_resp_item * xhdr_resp_item_new(uint32_t article,
1361 char * value)
1362{
1363 struct newsnntp_xhdr_resp_item * n;
1364
1365 n = malloc(sizeof(* n));
1366 if (n == NULL)
1367 return NULL;
1368
1369 n->hdr_value = strdup(value);
1370 if (n->hdr_value == NULL) {
1371 free(n);
1372 return NULL;
1373 }
1374
1375 n->hdr_article = article;
1376
1377 return n;
1378}
1379
1380static void xhdr_resp_item_free(struct newsnntp_xhdr_resp_item * n)
1381{
1382 if (n->hdr_value)
1383 free(n->hdr_value);
1384 free(n);
1385}
1386
1387static void xhdr_resp_list_free(clist * l)
1388{
1389 clist_foreach(l, (clist_func) xhdr_resp_item_free, NULL);
1390 clist_free(l);
1391}
1392
1393static clist * read_xhdr_resp_list(newsnntp * f);
1394
1395static int newsnntp_xhdr_resp(newsnntp * f, clist ** result);
1396
1397int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article,
1398 clist ** result)
1399{
1400 char command[NNTP_STRING_SIZE];
1401 int r;
1402
1403 snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i\r\n", header, article);
1404 r = send_command(f, command);
1405 if (r == -1)
1406 return NEWSNNTP_ERROR_STREAM;
1407
1408 return newsnntp_xhdr_resp(f, result);
1409}
1410
1411int newsnntp_xhdr_range(newsnntp * f, const char * header,
1412 uint32_t rangeinf, uint32_t rangesup,
1413 clist ** result)
1414{
1415 char command[NNTP_STRING_SIZE];
1416 int r;
1417
1418 snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i-%i\r\n", header,
1419 rangeinf, rangesup);
1420 r = send_command(f, command);
1421 if (r == -1)
1422 return NEWSNNTP_ERROR_STREAM;
1423
1424 return newsnntp_xhdr_resp(f, result);
1425}
1426
1427void newsnntp_xhdr_free(clist * l)
1428{
1429 xhdr_resp_list_free(l);
1430}
1431
1432static int newsnntp_xhdr_resp(newsnntp * f, clist ** result)
1433{
1434 int r;
1435 char * response;
1436
1437 response = read_line(f);
1438 if (response == NULL)
1439 return NEWSNNTP_ERROR_STREAM;
1440
1441 r = parse_response(f, response);
1442
1443 switch (r) {
1444 case 480:
1445 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1446
1447 case 381:
1448 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1449
1450 case 221:
1451 * result = read_xhdr_resp_list(f);
1452 return NEWSNNTP_NO_ERROR;
1453
1454 case 412:
1455 return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED;
1456
1457 case 420:
1458 return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED;
1459
1460 case 430:
1461 return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND;
1462
1463 case 502:
1464 return NEWSNNTP_ERROR_NO_PERMISSION;
1465
1466 default:
1467 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1468 }
1469}
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484/* ********************** XOVER ***************************** */
1485
1486static struct newsnntp_xover_resp_item *
1487xover_resp_item_new(uint32_t article,
1488 char * subject,
1489 char * author,
1490 char * date,
1491 char * message_id,
1492 char * references,
1493 size_t size,
1494 uint32_t line_count,
1495 clist * others)
1496{
1497 struct newsnntp_xover_resp_item * n;
1498
1499 n = malloc(sizeof(* n));
1500 if (n == NULL)
1501 return NULL;
1502
1503 n->ovr_subject = strdup(subject);
1504 if (n->ovr_subject == NULL) {
1505 free(n);
1506 return NULL;
1507 }
1508
1509 n->ovr_author = strdup(author);
1510 if (n->ovr_author == NULL) {
1511 free(n->ovr_subject);
1512 free(n);
1513 return NULL;
1514 }
1515
1516 n->ovr_date = strdup(date);
1517 if (n->ovr_date == NULL) {
1518 free(n->ovr_subject);
1519 free(n->ovr_author);
1520 free(n);
1521 return NULL;
1522 }
1523
1524 n->ovr_message_id = strdup(message_id);
1525 if (n->ovr_message_id == NULL) {
1526 free(n->ovr_subject);
1527 free(n->ovr_author);
1528 free(n->ovr_date);
1529 free(n);
1530 return NULL;
1531 }
1532
1533 n->ovr_references = strdup(references);
1534 if (n->ovr_references == NULL) {
1535 free(n->ovr_subject);
1536 free(n->ovr_author);
1537 free(n->ovr_date);
1538 free(n->ovr_message_id);
1539 free(n);
1540 return NULL;
1541 }
1542
1543 n->ovr_article = article;
1544 n->ovr_size = size;
1545 n->ovr_line_count = line_count;
1546 n->ovr_others = others;
1547
1548 return n;
1549}
1550
1551void xover_resp_item_free(struct newsnntp_xover_resp_item * n)
1552{
1553 if (n->ovr_subject)
1554 free(n->ovr_subject);
1555 if (n->ovr_author)
1556 free(n->ovr_author);
1557 if (n->ovr_date)
1558 free(n->ovr_date);
1559 if (n->ovr_message_id)
1560 free(n->ovr_message_id);
1561 if (n->ovr_references)
1562 free(n->ovr_references);
1563 clist_foreach(n->ovr_others, (clist_func) free, NULL);
1564 clist_free(n->ovr_others);
1565
1566 free(n);
1567}
1568
1569void newsnntp_xover_resp_list_free(clist * l)
1570{
1571 clist_foreach(l, (clist_func) xover_resp_item_free, NULL);
1572 clist_free(l);
1573}
1574
1575static clist * read_xover_resp_list(newsnntp * f);
1576
1577
1578static int newsnntp_xover_resp(newsnntp * f, clist ** result);
1579
1580int newsnntp_xover_single(newsnntp * f, uint32_t article,
1581 struct newsnntp_xover_resp_item ** result)
1582{
1583 char command[NNTP_STRING_SIZE];
1584 int r;
1585 clist * list;
1586 clistiter * cur;
1587 struct newsnntp_xover_resp_item * item;
1588
1589 snprintf(command, NNTP_STRING_SIZE, "XOVER %i\r\n", article);
1590 r = send_command(f, command);
1591 if (r == -1)
1592 return NEWSNNTP_ERROR_STREAM;
1593
1594 r = newsnntp_xover_resp(f, &list);
1595 if (r != NEWSNNTP_NO_ERROR)
1596 return r;
1597
1598 cur = clist_begin(list);
1599 item = clist_content(cur);
1600 clist_free(list);
1601
1602 * result = item;
1603
1604 return r;
1605}
1606
1607int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup,
1608 clist ** result)
1609{
1610 int r;
1611 char command[NNTP_STRING_SIZE];
1612
1613 snprintf(command, NNTP_STRING_SIZE, "XOVER %i-%i\r\n", rangeinf, rangesup);
1614 r = send_command(f, command);
1615 if (r == -1)
1616 return NEWSNNTP_ERROR_STREAM;
1617
1618 return newsnntp_xover_resp(f, result);
1619}
1620
1621static int newsnntp_xover_resp(newsnntp * f, clist ** result)
1622{
1623 int r;
1624 char * response;
1625
1626 response = read_line(f);
1627 if (response == NULL)
1628 return NEWSNNTP_ERROR_STREAM;
1629
1630 r = parse_response(f, response);
1631
1632 switch (r) {
1633 case 480:
1634 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1635
1636 case 381:
1637 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1638
1639 case 224:
1640 * result = read_xover_resp_list(f);
1641 return NEWSNNTP_NO_ERROR;
1642
1643 case 412:
1644 return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED;
1645
1646 case 420:
1647 return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED;
1648
1649 case 502:
1650 return NEWSNNTP_ERROR_NO_PERMISSION;
1651
1652 default:
1653 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1654 }
1655}
1656
1657
1658
1659
1660
1661
1662
1663/* ********************** AUTHINFO GENERIC ***************************** */
1664
1665int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator,
1666 const char * arguments)
1667{
1668 char command[NNTP_STRING_SIZE];
1669 int r;
1670 char * response;
1671
1672 snprintf(command, NNTP_STRING_SIZE, "AUTHINFO GENERIC %s %s\r\n",
1673 authentificator, arguments);
1674 r = send_command(f, command);
1675 if (r == -1)
1676 return NEWSNNTP_ERROR_STREAM;
1677
1678 response = read_line(f);
1679 if (response == NULL)
1680 return NEWSNNTP_ERROR_STREAM;
1681
1682 r = parse_response(f, response);
1683
1684 switch (r) {
1685 case 480:
1686 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME;
1687
1688 case 381:
1689 return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD;
1690
1691 case 281:
1692 return NEWSNNTP_NO_ERROR;
1693
1694 case 500:
1695 return NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD;
1696
1697 case 501:
1698 return NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED;
1699
1700 case 502:
1701 return NEWSNNTP_ERROR_NO_PERMISSION;
1702
1703 case 503:
1704 return NEWSNNTP_ERROR_PROGRAM_ERROR;
1705
1706 default:
1707 return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE;
1708 }
1709}
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729static int parse_space(char ** line)
1730{
1731 char * p;
1732
1733 p = * line;
1734
1735 while ((* p == ' ') || (* p == '\t'))
1736 p ++;
1737
1738 if (p != * line) {
1739 * line = p;
1740 return TRUE;
1741 }
1742 else
1743 return FALSE;
1744}
1745
1746static char * cut_token(char * line)
1747{
1748 char * p;
1749 char * p_tab;
1750 char * p_space;
1751
1752 p = line;
1753
1754 p_space = strchr(line, ' ');
1755 p_tab = strchr(line, '\t');
1756 if (p_tab == NULL)
1757 p = p_space;
1758 else if (p_space == NULL)
1759 p = p_tab;
1760 else {
1761 if (p_tab < p_space)
1762 p = p_tab;
1763 else
1764 p = p_space;
1765 }
1766 if (p == NULL)
1767 return NULL;
1768 * p = 0;
1769 p ++;
1770
1771 return p;
1772}
1773
1774static int parse_response(newsnntp * f, char * response)
1775{
1776 int code;
1777
1778 code = strtol(response, &response, 10);
1779
1780 if (response == NULL) {
1781 f->nntp_response = NULL;
1782 return code;
1783 }
1784
1785 parse_space(&response);
1786
1787 if (mmap_string_assign(f->nntp_response_buffer, response) != NULL)
1788 f->nntp_response = f->nntp_response_buffer->str;
1789 else
1790 f->nntp_response = NULL;
1791
1792 return code;
1793}
1794
1795
1796static char * read_line(newsnntp * f)
1797{
1798 return mailstream_read_line_remove_eol(f->nntp_stream, f->nntp_stream_buffer);
1799}
1800
1801static char * read_multiline(newsnntp * f, size_t size,
1802 MMAPString * multiline_buffer)
1803{
1804 return mailstream_read_multiline(f->nntp_stream, size,
1805 f->nntp_stream_buffer, multiline_buffer,
1806 f->nntp_progr_rate, f->nntp_progr_fun);
1807}
1808
1809
1810
1811
1812
1813
1814
1815static int parse_group_info(char * response,
1816 struct newsnntp_group_info ** result)
1817{
1818 char * line;
1819 uint32_t first;
1820 uint32_t last;
1821 uint32_t count;
1822 char * name;
1823 struct newsnntp_group_info * info;
1824
1825 line = response;
1826
1827 count = strtoul(line, &line, 10);
1828 if (!parse_space(&line))
1829 return FALSE;
1830
1831 first = strtoul(line, &line, 10);
1832 if (!parse_space(&line))
1833 return FALSE;
1834
1835 last = strtoul(line, &line, 10);
1836 if (!parse_space(&line))
1837 return FALSE;
1838
1839 name = line;
1840
1841 info = group_info_init(name, first, last, count, FALSE);
1842 if (info == NULL)
1843 return FALSE;
1844
1845 * result = info;
1846
1847 return TRUE;
1848}
1849
1850
1851static clist * read_groups_list(newsnntp * f)
1852{
1853 char * line;
1854 char * group_name;
1855 uint32_t first;
1856 uint32_t last;
1857 uint32_t count;
1858 int type;
1859 clist * groups_list;
1860 struct newsnntp_group_info * n;
1861 int r;
1862
1863 groups_list = clist_new();
1864 if (groups_list == NULL)
1865 goto err;
1866
1867 while (1) {
1868 char * p;
1869
1870 line = read_line(f);
1871 if (line == NULL)
1872 goto free_list;
1873
1874 if (mailstream_is_end_multiline(line))
1875 break;
1876
1877 p = cut_token(line);
1878 if (p == NULL)
1879 continue;
1880
1881 group_name = line;
1882 line = p;
1883
1884 last = strtol(line, &line, 10);
1885 if (!parse_space(&line))
1886 continue;
1887
1888 first = strtol(line, &line, 10);
1889 if (!parse_space(&line))
1890 continue;
1891
1892 count = last - first + 1;
1893
1894 type = * line;
1895
1896 n = group_info_init(group_name, first, last, count, type);
1897 if (n == NULL)
1898 goto free_list;
1899
1900 r = clist_append(groups_list, n);
1901 if (r < 0) {
1902 group_info_free(n);
1903 goto free_list;
1904 }
1905 }
1906
1907 return groups_list;
1908
1909 free_list:
1910 group_info_list_free(groups_list);
1911 err:
1912 return NULL;
1913}
1914
1915
1916static clist * read_headers_list(newsnntp * f)
1917{
1918 char * line;
1919 clist * headers_list;
1920 char * header;
1921 int r;
1922
1923 headers_list = clist_new();
1924 if (headers_list == NULL)
1925 goto err;
1926
1927 while (1) {
1928 line = read_line(f);
1929
1930 if (line == NULL)
1931 goto free_list;
1932
1933 if (mailstream_is_end_multiline(line))
1934 break;
1935
1936 header = strdup(line);
1937 if (header == NULL)
1938 goto free_list;
1939
1940 r = clist_append(headers_list, header);
1941 if (r < 0) {
1942 free(header);
1943 goto free_list;
1944 }
1945 }
1946
1947 return headers_list;
1948
1949 free_list:
1950 headers_list_free(headers_list);
1951 err:
1952 return NULL;
1953}
1954
1955
1956
1957
1958static clist * read_group_time_list(newsnntp * f)
1959{
1960 char * line;
1961 char * group_name;
1962 time_t date;
1963 char * email;
1964 clist * group_time_list;
1965 struct newsnntp_group_time * n;
1966 int r;
1967
1968 group_time_list = clist_new();
1969 if (group_time_list == NULL)
1970 goto err;
1971
1972 while (1) {
1973 char * p;
1974 char * remaining;
1975
1976 line = read_line(f);
1977
1978 if (line == NULL)
1979 goto free_list;
1980
1981 if (mailstream_is_end_multiline(line))
1982 break;
1983
1984 p = cut_token(line);
1985 if (p == NULL)
1986 continue;
1987
1988 date = strtoul(p, &remaining, 10);
1989
1990 p = remaining;
1991 parse_space(&p);
1992
1993 email = p;
1994
1995 group_name = line;
1996
1997 n = group_time_new(group_name, date, email);
1998 if (n == NULL)
1999 goto free_list;
2000
2001 r = clist_append(group_time_list, n);
2002 if (r < 0) {
2003 group_time_free(n);
2004 goto free_list;
2005 }
2006 }
2007
2008 return group_time_list;
2009
2010 free_list:
2011 group_time_list_free(group_time_list);
2012 err:
2013 return NULL;
2014}
2015
2016
2017
2018
2019static clist * read_distrib_value_meaning_list(newsnntp * f)
2020{
2021 char * line;
2022 char * value;
2023 char * meaning;
2024 clist * distrib_value_meaning_list;
2025 struct newsnntp_distrib_value_meaning * n;
2026 int r;
2027
2028 distrib_value_meaning_list = clist_new();
2029 if (distrib_value_meaning_list == NULL)
2030 goto err;
2031
2032 while (1) {
2033 char * p;
2034
2035 line = read_line(f);
2036 if (line == NULL)
2037 goto free_list;
2038
2039 if (mailstream_is_end_multiline(line))
2040 break;
2041
2042 p = cut_token(line);
2043 if (p == NULL)
2044 continue;
2045
2046 meaning = p;
2047
2048 value = line;
2049
2050 n = distrib_value_meaning_new(value, meaning);
2051 if (n == NULL)
2052 goto free_list;
2053
2054 r = clist_append(distrib_value_meaning_list, n);
2055 if (r < 0) {
2056 distrib_value_meaning_free(n);
2057 goto free_list;
2058 }
2059 }
2060
2061 return distrib_value_meaning_list;
2062
2063 free_list:
2064 distrib_value_meaning_list_free(distrib_value_meaning_list);
2065 err:
2066 return NULL;
2067}
2068
2069
2070
2071
2072static clist * read_distrib_default_value_list(newsnntp * f)
2073{
2074 char * line;
2075 uint32_t weight;
2076 char * group_pattern;
2077 char * meaning;
2078 clist * distrib_default_value_list;
2079 struct newsnntp_distrib_default_value * n;
2080 int r;
2081
2082 distrib_default_value_list = clist_new();
2083 if (distrib_default_value_list == NULL)
2084 goto err;
2085
2086 while (1) {
2087 char * p;
2088 char * remaining;
2089
2090 line = read_line(f);
2091 if (line == NULL)
2092 goto free_list;
2093
2094 if (mailstream_is_end_multiline(line))
2095 break;
2096
2097 p = line;
2098
2099 weight = strtoul(p, &remaining, 10);
2100 p = remaining;
2101 parse_space(&p);
2102
2103 p = cut_token(line);
2104 if (p == NULL)
2105 continue;
2106
2107 meaning = p;
2108 group_pattern = line;
2109
2110 n = distrib_default_value_new(weight, group_pattern, meaning);
2111 if (n == NULL)
2112 goto free_list;
2113
2114 r = clist_append(distrib_default_value_list, n);
2115 if (r < 0) {
2116 distrib_default_value_free(n);
2117 goto free_list;
2118 }
2119 }
2120
2121 return distrib_default_value_list;
2122
2123 free_list:
2124 distrib_default_value_list_free(distrib_default_value_list);
2125 err:
2126 return NULL;
2127}
2128
2129
2130
2131static clist * read_group_description_list(newsnntp * f)
2132{
2133 char * line;
2134 char * group_name;
2135 char * description;
2136 clist * group_description_list;
2137 struct newsnntp_group_description * n;
2138 int r;
2139
2140 group_description_list = clist_new();
2141 if (group_description_list == NULL)
2142 goto err;
2143
2144 while (1) {
2145 char * p;
2146
2147 line = read_line(f);
2148 if (line == NULL)
2149 goto free_list;
2150
2151 if (mailstream_is_end_multiline(line))
2152 break;
2153
2154 p = cut_token(line);
2155 if (p == NULL)
2156 continue;
2157
2158 description = p;
2159
2160 group_name = line;
2161
2162 n = group_description_new(group_name, description);
2163 if (n == NULL)
2164 goto free_list;
2165
2166 r = clist_append(group_description_list, n);
2167 if (r < 0) {
2168 group_description_free(n);
2169 goto free_list;
2170 }
2171 }
2172
2173 return group_description_list;
2174
2175 free_list:
2176 group_description_list_free(group_description_list);
2177 err:
2178 return NULL;
2179}
2180
2181
2182
2183static clist * read_subscriptions_list(newsnntp * f)
2184{
2185 char * line;
2186 clist * subscriptions_list;
2187 char * group_name;
2188 int r;
2189
2190 subscriptions_list = clist_new();
2191 if (subscriptions_list == NULL)
2192 goto err;
2193
2194 while (1) {
2195 line = read_line(f);
2196
2197 if (line == NULL)
2198 goto free_list;
2199
2200 if (mailstream_is_end_multiline(line))
2201 break;
2202
2203 group_name = strdup(line);
2204 if (group_name == NULL)
2205 goto free_list;
2206
2207 r = clist_append(subscriptions_list, group_name);
2208 if (r < 0) {
2209 free(group_name);
2210 goto free_list;
2211 }
2212 }
2213
2214 return subscriptions_list;
2215
2216 free_list:
2217 subscriptions_list_free(subscriptions_list);
2218 err:
2219 return NULL;
2220}
2221
2222
2223
2224static clist * read_articles_list(newsnntp * f)
2225{
2226 char * line;
2227 clist * articles_list;
2228 uint32_t * article_num;
2229 int r;
2230
2231 articles_list = clist_new();
2232 if (articles_list == NULL)
2233 goto err;
2234
2235 while (1) {
2236 line = read_line(f);
2237 if (line == NULL)
2238 goto free_list;
2239
2240 if (mailstream_is_end_multiline(line))
2241 break;
2242
2243 article_num = malloc(sizeof(* article_num));
2244 if (article_num == NULL)
2245 goto free_list;
2246 * article_num = atoi(line);
2247
2248 r = clist_append(articles_list, article_num);
2249 if (r < 0) {
2250 free(article_num);
2251 goto free_list;
2252 }
2253 }
2254
2255 return articles_list;
2256
2257 free_list:
2258 articles_list_free(articles_list);
2259 err:
2260 return NULL;
2261}
2262
2263static clist * read_xhdr_resp_list(newsnntp * f)
2264{
2265 char * line;
2266 uint32_t article;
2267 char * value;
2268 clist * xhdr_resp_list;
2269 struct newsnntp_xhdr_resp_item * n;
2270 int r;
2271
2272 xhdr_resp_list = clist_new();
2273 if (xhdr_resp_list == NULL)
2274 goto err;
2275
2276 while (1) {
2277 line = read_line(f);
2278
2279 if (line == NULL)
2280 goto free_list;
2281
2282 if (mailstream_is_end_multiline(line))
2283 break;
2284
2285 article = strtoul(line, &line, 10);
2286 if (!parse_space(&line))
2287 continue;
2288
2289 value = line;
2290
2291 n = xhdr_resp_item_new(article, value);
2292 if (n == NULL)
2293 goto free_list;
2294
2295 r = clist_append(xhdr_resp_list, n);
2296 if (r < 0) {
2297 xhdr_resp_item_free(n);
2298 goto free_list;
2299 }
2300 }
2301
2302 return xhdr_resp_list;
2303
2304 free_list:
2305 xhdr_resp_list_free(xhdr_resp_list);
2306 err:
2307 return NULL;
2308}
2309
2310
2311static clist * read_xover_resp_list(newsnntp * f)
2312{
2313 char * line;
2314 clist * xover_resp_list;
2315 struct newsnntp_xover_resp_item * n;
2316 clist * values_list;
2317 clistiter * current;
2318 uint32_t article;
2319 char * subject;
2320 char * author;
2321 char * date;
2322 char * message_id;
2323 char * references;
2324 size_t size;
2325 uint32_t line_count;
2326 clist * others;
2327 int r;
2328
2329 xover_resp_list = clist_new();
2330 if (xover_resp_list == NULL)
2331 goto err;
2332
2333 while (1) {
2334 char * p;
2335
2336 line = read_line(f);
2337
2338 if (line == NULL)
2339 goto free_list;
2340
2341 if (mailstream_is_end_multiline(line))
2342 break;
2343
2344 /* parse the data separated with \t */
2345
2346 values_list = clist_new();
2347 if (values_list == NULL)
2348 goto free_list;
2349
2350 while ((p = strchr(line, '\t')) != NULL) {
2351 * p = 0;
2352 p ++;
2353
2354 r = clist_append(values_list, line);
2355 if (r < 0)
2356 goto free_values_list;
2357 line = p;
2358 }
2359
2360 r = clist_append(values_list, line);
2361 if (r < 0)
2362 goto free_values_list;
2363
2364 /* set the known data */
2365 current = clist_begin(values_list);
2366 article = atoi((char *) clist_content(current));
2367
2368 current = clist_next(current);
2369 if (current == NULL) {
2370 clist_free(values_list);
2371 continue;
2372 }
2373 subject = clist_content(current);
2374
2375 current = clist_next(current);
2376 if (current == NULL) {
2377 clist_free(values_list);
2378 continue;
2379 }
2380 author = clist_content(current);
2381
2382 current = clist_next(current);
2383 if (current == NULL) {
2384 clist_free(values_list);
2385 continue;
2386 }
2387 date = clist_content(current);
2388
2389 current = clist_next(current);
2390 if (current == NULL) {
2391 clist_free(values_list);
2392 continue;
2393 }
2394 message_id = clist_content(current);
2395
2396 current = clist_next(current);
2397 if (current == NULL) {
2398 clist_free(values_list);
2399 continue;
2400 }
2401 references = clist_content(current);
2402
2403 current = clist_next(current);
2404 if (current == NULL) {
2405 clist_free(values_list);
2406 continue;
2407 }
2408 size = atoi((char *) clist_content(current));
2409
2410 current = clist_next(current);
2411 if (current == NULL) {
2412 clist_free(values_list);
2413 continue;
2414 }
2415 line_count = atoi((char *) clist_content(current));
2416
2417 current = clist_next(current);
2418
2419 /* make a copy of the other data */
2420 others = clist_new();
2421 if (others == NULL) {
2422 goto free_values_list;
2423 }
2424
2425 while (current) {
2426 char * val;
2427
2428 val = strdup(clist_content(current));
2429 if (val == NULL) {
2430 clist_foreach(others, (clist_func) free, NULL);
2431 clist_free(others);
2432 goto free_list;
2433 }
2434
2435 r = clist_append(others, val);
2436 if (r < 0) {
2437 goto free_list;
2438 }
2439
2440 current = clist_next(current);
2441 }
2442
2443 clist_free(values_list);
2444
2445 n = xover_resp_item_new(article, subject, author, date, message_id,
2446 references, size, line_count, others);
2447 if (n == NULL) {
2448 clist_foreach(others, (clist_func) free, NULL);
2449 clist_free(others);
2450 goto free_list;
2451 }
2452
2453 r = clist_append(xover_resp_list, n);
2454 if (r < 0) {
2455 xover_resp_item_free(n);
2456 goto free_list;
2457 }
2458 }
2459
2460 return xover_resp_list;
2461
2462 free_list:
2463 newsnntp_xover_resp_list_free(xover_resp_list);
2464 err:
2465 return NULL;
2466
2467 free_values_list:
2468 clist_foreach(values_list, (clist_func) free, NULL);
2469 clist_free(values_list);
2470 return NULL;
2471}
2472
2473static int send_command(newsnntp * f, char * command)
2474{
2475 ssize_t r;
2476
2477 r = mailstream_write(f->nntp_stream, command, strlen(command));
2478 if (r == -1)
2479 return -1;
2480
2481 r = mailstream_flush(f->nntp_stream);
2482 if (r == -1)
2483 return -1;
2484
2485 return 0;
2486}
diff --git a/libetpan/src/low-level/nntp/newsnntp.h b/libetpan/src/low-level/nntp/newsnntp.h
new file mode 100644
index 0000000..dd65ee2
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp.h
@@ -0,0 +1,187 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_H
37
38#define NEWSNNTP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <sys/types.h>
46#include <time.h>
47
48#include <libetpan/clist.h>
49#include <libetpan/mailstream.h>
50#include <libetpan/newsnntp_socket.h>
51#include <libetpan/newsnntp_ssl.h>
52#include <libetpan/newsnntp_types.h>
53
54
55newsnntp * newsnntp_new(size_t nntp_progr_rate,
56 progress_function * nntp_progr_fun);
57void newsnntp_free(newsnntp * f);
58
59int newsnntp_quit(newsnntp * f);
60int newsnntp_connect(newsnntp * f, mailstream * s);
61
62int newsnntp_head(newsnntp * f, uint32_t index, char ** result,
63 size_t * result_len);
64int newsnntp_article(newsnntp * f, uint32_t index, char ** result,
65 size_t * result_len);
66int newsnntp_body(newsnntp * f, uint32_t index, char ** result,
67 size_t * result_len);
68
69void newsnntp_head_free(char * str);
70void newsnntp_article_free(char * str);
71void newsnntp_body_free(char * str);
72
73int newsnntp_mode_reader(newsnntp * f);
74
75int newsnntp_date(newsnntp * f, struct tm * tm);
76
77int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator,
78 const char * arguments);
79
80int newsnntp_authinfo_username(newsnntp * f, const char * username);
81int newsnntp_authinfo_password(newsnntp * f, const char * password);
82
83int newsnntp_post(newsnntp * f, const char * message, size_t size);
84
85
86
87
88
89
90/******************* requests ******************************/
91
92int newsnntp_group(newsnntp * f, const char * groupname,
93 struct newsnntp_group_info ** info);
94void newsnntp_group_free(struct newsnntp_group_info * info);
95
96/*
97 elements are struct newsnntp_group_info *
98 */
99
100int newsnntp_list(newsnntp * f, clist ** result);
101void newsnntp_list_free(clist * l);
102
103/*
104 elements are char *
105*/
106
107int newsnntp_list_overview_fmt(newsnntp * f, clist ** result);
108void newsnntp_list_overview_fmt_free(clist * l);
109
110/*
111 elements are struct newsnntp_group_info *
112*/
113
114int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result);
115void newsnntp_list_active_free(clist * l);
116
117/*
118 elements are struct newsnntp_group_time *
119*/
120
121int newsnntp_list_active_times(newsnntp * f, clist ** result);
122void newsnntp_list_active_times_free(clist * l);
123
124/*
125 elements are struct newsnntp_distrib_value_meaning *
126*/
127
128int newsnntp_list_distribution(newsnntp * f, clist ** result);
129void newsnntp_list_distribution_free(clist * l);
130
131/*
132 elements are struct newsnntp_distrib_default_value *
133*/
134
135int newsnntp_list_distrib_pats(newsnntp * f, clist ** result);
136void newsnntp_list_distrib_pats_free(clist * l);
137
138/*
139 elements are struct newsnntp_group_description *
140*/
141
142int newsnntp_list_newsgroups(newsnntp * f, const char * pattern,
143 clist ** result);
144void newsnntp_list_newsgroups_free(clist * l);
145
146/*
147 elements are char *
148*/
149
150int newsnntp_list_subscriptions(newsnntp * f, clist ** result);
151void newsnntp_list_subscriptions_free(clist * l);
152
153/*
154 elements are uint32_t *
155*/
156
157int newsnntp_listgroup(newsnntp * f, const char * group_name,
158 clist ** result);
159void newsnntp_listgroup_free(clist * l);
160
161/*
162 elements are struct newsnntp_xhdr_resp_item *
163*/
164
165int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article,
166 clist ** result);
167int newsnntp_xhdr_range(newsnntp * f, const char * header,
168 uint32_t rangeinf, uint32_t rangesup,
169 clist ** result);
170void newsnntp_xhdr_free(clist * l);
171
172/*
173 elements are struct newsnntp_xover_resp_item *
174*/
175
176int newsnntp_xover_single(newsnntp * f, uint32_t article,
177 struct newsnntp_xover_resp_item ** result);
178int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup,
179 clist ** result);
180void xover_resp_item_free(struct newsnntp_xover_resp_item * n);
181void newsnntp_xover_resp_list_free(clist * l);
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif
diff --git a/libetpan/src/low-level/nntp/newsnntp_socket.c b/libetpan/src/low-level/nntp/newsnntp_socket.c
new file mode 100644
index 0000000..3fdd219
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp_socket.c
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "newsnntp_socket.h"
37
38#include "newsnntp.h"
39
40#include "connect.h"
41
42#include <netinet/in.h>
43#include <unistd.h>
44
45#define DEFAULT_NNTP_PORT 119
46#define SERVICE_NAME_NNTP "nntp"
47#define SERVICE_TYPE_TCP "tcp"
48
49int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port)
50{
51 int s;
52 mailstream * stream;
53
54 if (port == 0) {
55 port = mail_get_service_port(SERVICE_NAME_NNTP, SERVICE_TYPE_TCP);
56 if (port == 0)
57 port = DEFAULT_NNTP_PORT;
58 port = ntohs(port);
59 }
60
61 /* Connection */
62
63 s = mail_tcp_connect(server, port);
64 if (s == -1)
65 return NEWSNNTP_ERROR_CONNECTION_REFUSED;
66
67 stream = mailstream_socket_open(s);
68 if (stream == NULL) {
69 close(s);
70 return NEWSNNTP_ERROR_MEMORY;
71 }
72
73 return newsnntp_connect(f, stream);
74}
diff --git a/libetpan/src/low-level/nntp/newsnntp_socket.h b/libetpan/src/low-level/nntp/newsnntp_socket.h
new file mode 100644
index 0000000..4a52f73
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp_socket.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_SOCKET_H
37
38#define NEWSNNTP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46
47#include <libetpan/newsnntp_types.h>
48
49int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/src/low-level/nntp/newsnntp_ssl.c b/libetpan/src/low-level/nntp/newsnntp_ssl.c
new file mode 100644
index 0000000..d2e2c5f
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp_ssl.c
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "newsnntp_ssl.h"
37
38#include "newsnntp.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_NNTPS_PORT 563
45#define SERVICE_NAME_NNTPS "nntps"
46#define SERVICE_TYPE_TCP "tcp"
47
48int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port)
49{
50 int s;
51 mailstream * stream;
52
53 if (port == 0) {
54 port = mail_get_service_port(SERVICE_NAME_NNTPS, SERVICE_TYPE_TCP);
55 if (port == 0)
56 port = DEFAULT_NNTPS_PORT;
57 port = ntohs(port);
58 }
59
60 /* Connection */
61
62 s = mail_tcp_connect(server, port);
63 if (s == -1)
64 return NEWSNNTP_ERROR_CONNECTION_REFUSED;
65
66 stream = mailstream_ssl_open(s);
67 if (stream == NULL) {
68 close(s);
69 return NEWSNNTP_ERROR_CONNECTION_REFUSED;
70 }
71
72 return newsnntp_connect(f, stream);
73}
diff --git a/libetpan/src/low-level/nntp/newsnntp_ssl.h b/libetpan/src/low-level/nntp/newsnntp_ssl.h
new file mode 100644
index 0000000..845484f
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp_ssl.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_SSL_H
37
38#define NEWSNNTP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45#include <inttypes.h>
46
47#include <libetpan/newsnntp_types.h>
48
49int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/src/low-level/nntp/newsnntp_types.h b/libetpan/src/low-level/nntp/newsnntp_types.h
new file mode 100644
index 0000000..821df46
--- a/dev/null
+++ b/libetpan/src/low-level/nntp/newsnntp_types.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef NEWSNNTP_TYPES_H
37
38#define NEWSNNTP_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <libetpan/clist.h>
46
47#include <libetpan/mailstream.h>
48#include <libetpan/mmapstring.h>
49
50enum {
51 NEWSNNTP_NO_ERROR = 0,
52 NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME,
53 NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD,
54 NEWSNNTP_ERROR_STREAM,
55 NEWSNNTP_ERROR_UNEXPECTED,
56 NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED,
57 NEWSNNTP_ERROR_NO_ARTICLE_SELECTED,
58 NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER,
59 NEWSNNTP_ERROR_ARTICLE_NOT_FOUND,
60 NEWSNNTP_ERROR_UNEXPECTED_RESPONSE,
61 NEWSNNTP_ERROR_INVALID_RESPONSE,
62 NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP,
63 NEWSNNTP_ERROR_POSTING_NOT_ALLOWED,
64 NEWSNNTP_ERROR_POSTING_FAILED,
65 NEWSNNTP_ERROR_PROGRAM_ERROR,
66 NEWSNNTP_ERROR_NO_PERMISSION,
67 NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD,
68 NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED,
69 NEWSNNTP_ERROR_CONNECTION_REFUSED,
70 NEWSNNTP_ERROR_MEMORY,
71 NEWSNNTP_ERROR_AUTHENTICATION_REJECTED,
72 NEWSNNTP_ERROR_BAD_STATE,
73};
74
75struct newsnntp
76{
77 mailstream * nntp_stream;
78
79 int nntp_readonly;
80
81 uint32_t nntp_progr_rate;
82 progress_function * nntp_progr_fun;
83
84 MMAPString * nntp_stream_buffer;
85 MMAPString * nntp_response_buffer;
86
87 char * nntp_response;
88};
89
90typedef struct newsnntp newsnntp;
91
92struct newsnntp_group_info
93{
94 char * grp_name;
95 uint32_t grp_first;
96 uint32_t grp_last;
97 uint32_t grp_count;
98 char grp_type;
99};
100
101struct newsnntp_group_time {
102 char * grp_name;
103 uint32_t grp_date;
104 char * grp_email;
105};
106
107struct newsnntp_distrib_value_meaning {
108 char * dst_value;
109 char * dst_meaning;
110};
111
112struct newsnntp_distrib_default_value {
113 uint32_t dst_weight;
114 char * dst_group_pattern;
115 char * dst_value;
116};
117
118struct newsnntp_group_description {
119 char * grp_name;
120 char * grp_description;
121};
122
123struct newsnntp_xhdr_resp_item {
124 uint32_t hdr_article;
125 char * hdr_value;
126};
127
128struct newsnntp_xover_resp_item {
129 uint32_t ovr_article;
130 char * ovr_subject;
131 char * ovr_author;
132 char * ovr_date;
133 char * ovr_message_id;
134 char * ovr_references;
135 size_t ovr_size;
136 uint32_t ovr_line_count;
137 clist * ovr_others;
138};
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/src/low-level/pop3/mailpop3.c b/libetpan/src/low-level/pop3/mailpop3.c
new file mode 100644
index 0000000..6f77a3a
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3.c
@@ -0,0 +1,1230 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 POP3 Protocol
38
39 RFC 1734
40 RFC 1939
41 RFC 2449
42
43 */
44
45#include "mailpop3.h"
46#include <stdio.h>
47#include <string.h>
48#include "md5.h"
49#include "mail.h"
50#include <stdlib.h>
51
52
53
54
55enum {
56 POP3_STATE_DISCONNECTED,
57 POP3_STATE_AUTHORIZATION,
58 POP3_STATE_TRANSACTION
59};
60
61
62
63/*
64 mailpop3_msg_info structure
65*/
66
67static struct mailpop3_msg_info *
68mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl)
69{
70 struct mailpop3_msg_info * msg;
71
72 msg = malloc(sizeof(* msg));
73 if (msg == NULL)
74 return NULL;
75 msg->msg_index = index;
76 msg->msg_size = size;
77 msg->msg_deleted = FALSE;
78 msg->msg_uidl = uidl;
79
80 return msg;
81}
82
83static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg)
84{
85 if (msg->msg_uidl != NULL)
86 free(msg->msg_uidl);
87 free(msg);
88}
89
90static void mailpop3_msg_info_tab_free(carray * msg_tab)
91{
92 unsigned int i;
93
94 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
95 struct mailpop3_msg_info * msg;
96
97 msg = carray_get(msg_tab, i);
98 mailpop3_msg_info_free(msg);
99 }
100 carray_free(msg_tab);
101}
102
103static void mailpop3_msg_info_tab_reset(carray * msg_tab)
104{
105 unsigned int i;
106
107 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
108 struct mailpop3_msg_info * msg;
109 msg = carray_get(msg_tab, i);
110 msg->msg_deleted = FALSE;
111 }
112}
113
114static inline struct mailpop3_msg_info *
115mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index)
116{
117 struct mailpop3_msg_info * msg;
118
119 if (index == 0)
120 return NULL;
121
122 if (index > carray_count(msg_tab))
123 return NULL;
124
125 msg = carray_get(msg_tab, index - 1);
126
127 return msg;
128}
129
130
131
132int mailpop3_get_msg_info(mailpop3 * f, unsigned int index,
133 struct mailpop3_msg_info ** result)
134{
135 carray * tab;
136 struct mailpop3_msg_info * info;
137
138 mailpop3_list(f, &tab);
139
140 if (tab == NULL)
141 return MAILPOP3_ERROR_BAD_STATE;
142
143 info = mailpop3_msg_info_tab_find_msg(tab, index);
144 if (info == NULL)
145 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
146
147 * result = info;
148
149 return MAILPOP3_NO_ERROR;
150}
151
152
153/*
154 mailpop3_capa
155*/
156
157struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param)
158{
159 struct mailpop3_capa * capa;
160
161 capa = malloc(sizeof(* capa));
162 if (capa == NULL)
163 return NULL;
164 capa->cap_name = name;
165 capa->cap_param = param;
166
167 return capa;
168}
169
170
171void mailpop3_capa_free(struct mailpop3_capa * capa)
172{
173 clist_foreach(capa->cap_param, (clist_func) free, NULL);
174 clist_free(capa->cap_param);
175 free(capa->cap_name);
176 free(capa);
177}
178
179/*
180 mailpop3 structure
181*/
182
183mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun)
184{
185 mailpop3 * f;
186
187 f = malloc(sizeof(* f));
188 if (f == NULL)
189 goto err;
190
191 f->pop3_timestamp = NULL;
192 f->pop3_response = NULL;
193
194 f->pop3_stream = NULL;
195
196 f->pop3_progr_rate = progr_rate;
197 f->pop3_progr_fun = progr_fun;
198
199 f->pop3_stream_buffer = mmap_string_new("");
200 if (f->pop3_stream_buffer == NULL)
201 goto free_f;
202
203 f->pop3_response_buffer = mmap_string_new("");
204 if (f->pop3_response_buffer == NULL)
205 goto free_stream_buffer;
206
207 f->pop3_msg_tab = NULL;
208 f->pop3_deleted_count = 0;
209 f->pop3_state = POP3_STATE_DISCONNECTED;
210
211 return f;
212
213 free_stream_buffer:
214 mmap_string_free(f->pop3_stream_buffer);
215 free_f:
216 free(f);
217 err:
218 return NULL;
219}
220
221
222
223void mailpop3_free(mailpop3 * f)
224{
225 if (f->pop3_stream)
226 mailpop3_quit(f);
227
228 mmap_string_free(f->pop3_response_buffer);
229 mmap_string_free(f->pop3_stream_buffer);
230
231 free(f);
232}
233
234
235
236
237
238
239
240
241
242
243
244/*
245 operations on mailpop3 structure
246*/
247
248#define RESPONSE_OK 0
249#define RESPONSE_ERR -1
250
251static int send_command(mailpop3 * f, char * command);
252
253static char * read_line(mailpop3 * f);
254
255static char * read_multiline(mailpop3 * f, size_t size,
256 MMAPString * multiline_buffer);
257
258static int parse_response(mailpop3 * f, char * response);
259
260
261/* get the timestamp in the connection response */
262
263#define TIMESTAMP_START '<'
264#define TIMESTAMP_END '>'
265
266static char * mailpop3_get_timestamp(char * response)
267{
268 char * begin_timestamp;
269 char * end_timestamp;
270 char * timestamp;
271 int len_timestamp;
272
273 if (response == NULL)
274 return NULL;
275
276 begin_timestamp = strchr(response, TIMESTAMP_START);
277
278 end_timestamp = NULL;
279 if (begin_timestamp != NULL) {
280 end_timestamp = strchr(begin_timestamp, TIMESTAMP_END);
281 if (end_timestamp == NULL)
282 begin_timestamp = NULL;
283 }
284
285 if (!begin_timestamp)
286 return NULL;
287
288 len_timestamp = end_timestamp - begin_timestamp + 1;
289
290 timestamp = malloc(len_timestamp + 1);
291 if (timestamp == NULL)
292 return NULL;
293 strncpy(timestamp, begin_timestamp, len_timestamp);
294 timestamp[len_timestamp] = '\0';
295
296 return timestamp;
297}
298
299/*
300 connect a stream to the mailpop3 structure
301*/
302
303int mailpop3_connect(mailpop3 * f, mailstream * s)
304{
305 char * response;
306 int r;
307 char * timestamp;
308
309 if (f->pop3_state != POP3_STATE_DISCONNECTED)
310 return MAILPOP3_ERROR_BAD_STATE;
311
312 f->pop3_stream = s;
313
314 response = read_line(f);
315
316 r = parse_response(f, response);
317 if (r != RESPONSE_OK)
318 return MAILPOP3_ERROR_UNAUTHORIZED;
319
320 f->pop3_state = POP3_STATE_AUTHORIZATION;
321
322 timestamp = mailpop3_get_timestamp(f->pop3_response);
323 if (timestamp != NULL)
324 f->pop3_timestamp = timestamp;
325
326 return MAILPOP3_NO_ERROR;
327}
328
329
330/*
331 disconnect from a pop3 server
332*/
333
334int mailpop3_quit(mailpop3 * f)
335{
336 char command[POP3_STRING_SIZE];
337 char * response;
338 int r;
339 int res;
340
341 if ((f->pop3_state != POP3_STATE_AUTHORIZATION)
342 && (f->pop3_state != POP3_STATE_TRANSACTION)) {
343 res = MAILPOP3_ERROR_BAD_STATE;
344 goto close;
345 }
346
347 snprintf(command, POP3_STRING_SIZE, "QUIT\r\n");
348 r = send_command(f, command);
349 if (r == -1) {
350 res = MAILPOP3_ERROR_STREAM;
351 goto close;
352 }
353
354 response = read_line(f);
355 if (response == NULL) {
356 res = MAILPOP3_ERROR_STREAM;
357 goto close;
358 }
359 parse_response(f, response);
360
361 res = MAILPOP3_NO_ERROR;
362
363 close:
364 mailstream_close(f->pop3_stream);
365
366 if (f->pop3_timestamp != NULL) {
367 free(f->pop3_timestamp);
368 f->pop3_timestamp = NULL;
369 }
370
371 f->pop3_stream = NULL;
372 if (f->pop3_msg_tab != NULL) {
373 mailpop3_msg_info_tab_free(f->pop3_msg_tab);
374 f->pop3_msg_tab = NULL;
375 }
376
377 f->pop3_state = POP3_STATE_DISCONNECTED;
378
379 return res;
380}
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413int mailpop3_apop(mailpop3 * f,
414 const char * user, const char * password)
415{
416 char command[POP3_STRING_SIZE];
417 MD5_CTX md5context;
418 unsigned char md5digest[16];
419 char md5string[33];
420 char * cmd_ptr;
421 int r;
422 int i;
423 char * response;
424
425 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
426 return MAILPOP3_ERROR_BAD_STATE;
427
428 if (f->pop3_timestamp == NULL)
429 return MAILPOP3_ERROR_APOP_NOT_SUPPORTED;
430
431 /* calculate md5 sum */
432
433 MD5Init(&md5context);
434 MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp));
435 MD5Update(&md5context, password, strlen (password));
436 MD5Final(md5digest, &md5context);
437
438 cmd_ptr = md5string;
439 for(i = 0 ; i < 16 ; i++, cmd_ptr += 2)
440 snprintf(cmd_ptr, 3, "%02x", md5digest[i]);
441 * cmd_ptr = 0;
442
443 /* send apop command */
444
445 snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string);
446 r = send_command(f, command);
447 if (r == -1)
448 return MAILPOP3_ERROR_STREAM;
449
450 response = read_line(f);
451
452 if (response == NULL)
453 return MAILPOP3_ERROR_STREAM;
454 r = parse_response(f, response);
455 if (r != RESPONSE_OK)
456 return MAILPOP3_ERROR_DENIED;
457
458 f->pop3_state = POP3_STATE_TRANSACTION;
459
460 return MAILPOP3_NO_ERROR;
461}
462
463int mailpop3_user(mailpop3 * f, const char * user)
464{
465 char command[POP3_STRING_SIZE];
466 int r;
467 char * response;
468
469 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
470 return MAILPOP3_ERROR_BAD_STATE;
471
472 /* send user command */
473
474 snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user);
475 r = send_command(f, command);
476 if (r == -1)
477 return MAILPOP3_ERROR_STREAM;
478
479 response = read_line(f);
480 if (response == NULL)
481 return MAILPOP3_ERROR_STREAM;
482 r = parse_response(f, response);
483
484 if (r != RESPONSE_OK)
485 return MAILPOP3_ERROR_BAD_USER;
486
487 return MAILPOP3_NO_ERROR;
488}
489
490int mailpop3_pass(mailpop3 * f, const char * password)
491{
492 char command[POP3_STRING_SIZE];
493 int r;
494 char * response;
495
496 if (f->pop3_state != POP3_STATE_AUTHORIZATION)
497 return MAILPOP3_ERROR_BAD_STATE;
498
499 /* send password command */
500
501 snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password);
502 r = send_command(f, command);
503 if (r == -1)
504 return MAILPOP3_ERROR_STREAM;
505
506 response = read_line(f);
507 if (response == NULL)
508 return MAILPOP3_ERROR_STREAM;
509 r = parse_response(f, response);
510
511 if (r != RESPONSE_OK)
512 return MAILPOP3_ERROR_BAD_PASSWORD;
513
514 f->pop3_state = POP3_STATE_TRANSACTION;
515
516 return MAILPOP3_NO_ERROR;
517}
518
519static int read_list(mailpop3 * f, carray ** result);
520
521
522
523static int read_uidl(mailpop3 * f, carray * msg_tab);
524
525
526
527static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab)
528{
529 char command[POP3_STRING_SIZE];
530 int r;
531 char * response;
532
533 if (f->pop3_state != POP3_STATE_TRANSACTION)
534 return MAILPOP3_ERROR_BAD_STATE;
535
536 /* send list command */
537
538 snprintf(command, POP3_STRING_SIZE, "UIDL\r\n");
539 r = send_command(f, command);
540 if (r == -1)
541 return MAILPOP3_ERROR_STREAM;
542
543 response = read_line(f);
544 if (response == NULL)
545 return MAILPOP3_ERROR_STREAM;
546 r = parse_response(f, response);
547
548 if (r != RESPONSE_OK)
549 return MAILPOP3_ERROR_CANT_LIST;
550
551 r = read_uidl(f, msg_tab);
552 if (r != MAILPOP3_NO_ERROR)
553 return r;
554
555 return MAILPOP3_NO_ERROR;
556}
557
558
559
560static int mailpop3_do_list(mailpop3 * f)
561{
562 char command[POP3_STRING_SIZE];
563 int r;
564 carray * msg_tab;
565 char * response;
566
567 if (f->pop3_msg_tab != NULL) {
568 mailpop3_msg_info_tab_free(f->pop3_msg_tab);
569 f->pop3_msg_tab = NULL;
570 }
571
572 if (f->pop3_state != POP3_STATE_TRANSACTION)
573 return MAILPOP3_ERROR_BAD_STATE;
574
575 /* send list command */
576
577 snprintf(command, POP3_STRING_SIZE, "LIST\r\n");
578 r = send_command(f, command);
579 if (r == -1)
580 return MAILPOP3_ERROR_STREAM;
581
582 response = read_line(f);
583 if (response == NULL)
584 return MAILPOP3_ERROR_STREAM;
585 r = parse_response(f, response);
586
587 if (r != RESPONSE_OK)
588 return MAILPOP3_ERROR_CANT_LIST;
589
590 r = read_list(f, &msg_tab);
591 if (r != MAILPOP3_NO_ERROR)
592 return r;
593
594 f->pop3_msg_tab = msg_tab;
595 f->pop3_deleted_count = 0;
596
597 mailpop3_do_uidl(f, msg_tab);
598
599 return MAILPOP3_NO_ERROR;
600}
601
602
603
604static void mailpop3_list_if_needed(mailpop3 * f)
605{
606 if (f->pop3_msg_tab == NULL)
607 mailpop3_do_list(f);
608}
609
610/*
611 mailpop3_list
612*/
613
614void mailpop3_list(mailpop3 * f, carray ** result)
615{
616 mailpop3_list_if_needed(f);
617 * result = f->pop3_msg_tab;
618}
619
620static inline struct mailpop3_msg_info *
621find_msg(mailpop3 * f, unsigned int index)
622{
623 mailpop3_list_if_needed(f);
624
625 if (f->pop3_msg_tab == NULL)
626 return NULL;
627
628 return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index);
629}
630
631
632
633
634
635
636
637
638static void mailpop3_multiline_response_free(char * str)
639{
640 mmap_string_unref(str);
641}
642
643void mailpop3_top_free(char * str)
644{
645 mailpop3_multiline_response_free(str);
646}
647
648void mailpop3_retr_free(char * str)
649{
650 mailpop3_multiline_response_free(str);
651}
652
653/*
654 mailpop3_retr
655
656 message content in (* result) is still there until the
657 next retrieve or top operation on the mailpop3 structure
658*/
659
660static int
661mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo,
662 char ** result, size_t * result_len)
663{
664 char * response;
665 char * result_multiline;
666 MMAPString * buffer;
667 int r;
668
669 response = read_line(f);
670 if (response == NULL)
671 return MAILPOP3_ERROR_STREAM;
672 r = parse_response(f, response);
673 if (r != RESPONSE_OK)
674 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
675
676 buffer = mmap_string_new("");
677 if (buffer == NULL)
678 return MAILPOP3_ERROR_MEMORY;
679
680 result_multiline = read_multiline(f, msginfo->msg_size, buffer);
681 if (result_multiline == NULL) {
682 mmap_string_free(buffer);
683 return MAILPOP3_ERROR_STREAM;
684 }
685 else {
686 r = mmap_string_ref(buffer);
687 if (r < 0) {
688 mmap_string_free(buffer);
689 return MAILPOP3_ERROR_MEMORY;
690 }
691
692 * result = result_multiline;
693 * result_len = buffer->len;
694 return MAILPOP3_NO_ERROR;
695 }
696}
697
698int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result,
699 size_t * result_len)
700{
701 char command[POP3_STRING_SIZE];
702 struct mailpop3_msg_info * msginfo;
703 int r;
704
705 if (f->pop3_state != POP3_STATE_TRANSACTION)
706 return MAILPOP3_ERROR_BAD_STATE;
707
708 msginfo = find_msg(f, index);
709
710 if (msginfo == NULL) {
711 f->pop3_response = NULL;
712 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
713 }
714
715 snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index);
716 r = send_command(f, command);
717 if (r == -1)
718 return MAILPOP3_ERROR_STREAM;
719
720 return mailpop3_get_content(f, msginfo, result, result_len);
721}
722
723int mailpop3_top(mailpop3 * f, unsigned int index,
724 unsigned int count, char ** result,
725 size_t * result_len)
726{
727 char command[POP3_STRING_SIZE];
728 struct mailpop3_msg_info * msginfo;
729 int r;
730
731 if (f->pop3_state != POP3_STATE_TRANSACTION)
732 return MAILPOP3_ERROR_BAD_STATE;
733
734 msginfo = find_msg(f, index);
735
736 if (msginfo == NULL) {
737 f->pop3_response = NULL;
738 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
739 }
740
741 snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count);
742 r = send_command(f, command);
743 if (r == -1)
744 return MAILPOP3_ERROR_STREAM;
745
746 return mailpop3_get_content(f, msginfo, result, result_len);
747}
748
749int mailpop3_dele(mailpop3 * f, unsigned int index)
750{
751 char command[POP3_STRING_SIZE];
752 struct mailpop3_msg_info * msginfo;
753 char * response;
754 int r;
755
756 if (f->pop3_state != POP3_STATE_TRANSACTION)
757 return MAILPOP3_ERROR_BAD_STATE;
758
759 msginfo = find_msg(f, index);
760
761 if (msginfo == NULL) {
762 f->pop3_response = NULL;
763 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
764 }
765
766 snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index);
767 r = send_command(f, command);
768 if (r == -1)
769 return MAILPOP3_ERROR_STREAM;
770
771 response = read_line(f);
772 if (response == NULL)
773 return MAILPOP3_ERROR_STREAM;
774 r = parse_response(f, response);
775 if (r != RESPONSE_OK)
776 return MAILPOP3_ERROR_NO_SUCH_MESSAGE;
777
778 msginfo->msg_deleted = TRUE;
779 f->pop3_deleted_count ++;
780
781 return MAILPOP3_NO_ERROR;
782}
783
784int mailpop3_noop(mailpop3 * f)
785{
786 char command[POP3_STRING_SIZE];
787 char * response;
788 int r;
789
790 if (f->pop3_state != POP3_STATE_TRANSACTION)
791 return MAILPOP3_ERROR_BAD_STATE;
792
793 snprintf(command, POP3_STRING_SIZE, "NOOP\r\n");
794 r = send_command(f, command);
795 if (r == -1)
796 return MAILPOP3_ERROR_STREAM;
797
798 response = read_line(f);
799 if (response == NULL)
800 return MAILPOP3_ERROR_STREAM;
801 parse_response(f, response);
802
803 return MAILPOP3_NO_ERROR;
804}
805
806int mailpop3_rset(mailpop3 * f)
807{
808 char command[POP3_STRING_SIZE];
809 char * response;
810 int r;
811
812 if (f->pop3_state != POP3_STATE_TRANSACTION)
813 return MAILPOP3_ERROR_BAD_STATE;
814
815 snprintf(command, POP3_STRING_SIZE, "RSET\r\n");
816 r = send_command(f, command);
817 if (r == -1)
818 return MAILPOP3_ERROR_STREAM;
819
820 response = read_line(f);
821 if (response == NULL)
822 return MAILPOP3_ERROR_STREAM;
823 parse_response(f, response);
824
825 if (f->pop3_msg_tab != NULL) {
826 mailpop3_msg_info_tab_reset(f->pop3_msg_tab);
827 f->pop3_deleted_count = 0;
828 }
829
830 return MAILPOP3_NO_ERROR;
831}
832
833
834
835static int read_capa_resp(mailpop3 * f, clist ** result);
836
837int mailpop3_capa(mailpop3 * f, clist ** result)
838{
839 clist * capa_list;
840 char command[POP3_STRING_SIZE];
841 int r;
842 char * response;
843
844 snprintf(command, POP3_STRING_SIZE, "CAPA\r\n");
845 r = send_command(f, command);
846 if (r == -1)
847 return MAILPOP3_ERROR_STREAM;
848
849 response = read_line(f);
850 if (response == NULL)
851 return MAILPOP3_ERROR_STREAM;
852 r = parse_response(f, response);
853
854 if (r != RESPONSE_OK)
855 return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED;
856
857 r = read_capa_resp(f, &capa_list);
858 if (r != MAILPOP3_NO_ERROR)
859 return r;
860
861 * result = capa_list;
862
863 return MAILPOP3_NO_ERROR;
864}
865
866void mailpop3_capa_resp_free(clist * capa_list)
867{
868 clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL);
869 clist_free(capa_list);
870}
871
872int mailpop3_stls(mailpop3 * f)
873{
874 char command[POP3_STRING_SIZE];
875 int r;
876 char * response;
877
878 snprintf(command, POP3_STRING_SIZE, "STLS\r\n");
879 r = send_command(f, command);
880 if (r == -1)
881 return MAILPOP3_ERROR_STREAM;
882
883 response = read_line(f);
884 if (response == NULL)
885 return MAILPOP3_ERROR_STREAM;
886 r = parse_response(f, response);
887
888 if (r != RESPONSE_OK)
889 return MAILPOP3_ERROR_STLS_NOT_SUPPORTED;
890
891 return MAILPOP3_NO_ERROR;
892}
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917#define RESP_OK_STR "+OK"
918#define RESP_ERR_STR "-ERR"
919
920
921static int parse_space(char ** line)
922{
923 char * p;
924
925 p = * line;
926
927 while ((* p == ' ') || (* p == '\t'))
928 p ++;
929
930 if (p != * line) {
931 * line = p;
932 return TRUE;
933 }
934 else
935 return FALSE;
936}
937
938static char * cut_token(char * line)
939{
940 char * p;
941 char * p_tab;
942 char * p_space;
943
944 p = line;
945
946 p_space = strchr(line, ' ');
947 p_tab = strchr(line, '\t');
948 if (p_tab == NULL)
949 p = p_space;
950 else if (p_space == NULL)
951 p = p_tab;
952 else {
953 if (p_tab < p_space)
954 p = p_tab;
955 else
956 p = p_space;
957 }
958 if (p == NULL)
959 return NULL;
960 * p = 0;
961 p ++;
962
963 return p;
964}
965
966
967static int parse_response(mailpop3 * f, char * response)
968{
969 char * msg;
970
971 if (response == NULL) {
972 f->pop3_response = NULL;
973 return RESPONSE_ERR;
974 }
975
976 if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) {
977
978 if (response[strlen(RESP_OK_STR)] == ' ')
979 msg = response + strlen(RESP_OK_STR) + 1;
980 else
981 msg = response + strlen(RESP_OK_STR);
982
983 if (mmap_string_assign(f->pop3_response_buffer, msg))
984 f->pop3_response = f->pop3_response_buffer->str;
985 else
986 f->pop3_response = NULL;
987
988 return RESPONSE_OK;
989 }
990 else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) {
991
992 if (response[strlen(RESP_ERR_STR)] == ' ')
993 msg = response + strlen(RESP_ERR_STR) + 1;
994 else
995 msg = response + strlen(RESP_ERR_STR);
996
997 if (mmap_string_assign(f->pop3_response_buffer, msg))
998 f->pop3_response = f->pop3_response_buffer->str;
999 else
1000 f->pop3_response = NULL;
1001 }
1002
1003 f->pop3_response = NULL;
1004 return RESPONSE_ERR;
1005}
1006
1007
1008
1009
1010
1011
1012
1013static int read_list(mailpop3 * f, carray ** result)
1014{
1015 unsigned int index;
1016 uint32_t size;
1017 carray * msg_tab;
1018 struct mailpop3_msg_info * msg;
1019 char * line;
1020
1021 msg_tab = carray_new(128);
1022 if (msg_tab == NULL)
1023 goto err;
1024
1025 while (1) {
1026 line = read_line(f);
1027 if (line == NULL)
1028 goto free_list;
1029
1030 if (mailstream_is_end_multiline(line))
1031 break;
1032
1033 index = strtol(line, &line, 10);
1034
1035 if (!parse_space(&line))
1036 continue;
1037
1038 size = strtol(line, &line, 10);
1039
1040 msg = mailpop3_msg_info_new(index, size, NULL);
1041 if (msg == NULL)
1042 goto free_list;
1043
1044 if (carray_count(msg_tab) < index) {
1045 int r;
1046
1047 r = carray_set_size(msg_tab, index);
1048 if (r == -1)
1049 goto free_list;
1050 }
1051
1052 carray_set(msg_tab, index - 1, msg);
1053 }
1054
1055 * result = msg_tab;
1056
1057 return MAILPOP3_NO_ERROR;
1058
1059 free_list:
1060 mailpop3_msg_info_tab_free(msg_tab);
1061 err:
1062 return MAILPOP3_ERROR_STREAM;
1063}
1064
1065
1066
1067static int read_uidl(mailpop3 * f, carray * msg_tab)
1068{
1069 unsigned int index;
1070 struct mailpop3_msg_info * msg;
1071 char * line;
1072
1073 while (1) {
1074 char * uidl;
1075
1076 line = read_line(f);
1077 if (line == NULL)
1078 goto err;
1079
1080 if (mailstream_is_end_multiline(line))
1081 break;
1082
1083 index = strtol(line, &line, 10);
1084
1085 if (!parse_space(&line))
1086 continue;
1087
1088 uidl = strdup(line);
1089 if (uidl == NULL)
1090 continue;
1091
1092 if (index > carray_count(msg_tab)) {
1093 free(uidl);
1094 continue;
1095 }
1096
1097 msg = carray_get(msg_tab, index - 1);
1098 if (msg == NULL) {
1099 free(uidl);
1100 continue;
1101 }
1102
1103 msg->msg_uidl = uidl;
1104 }
1105
1106 return MAILPOP3_NO_ERROR;
1107
1108 err:
1109 return MAILPOP3_ERROR_STREAM;
1110}
1111
1112
1113
1114static int read_capa_resp(mailpop3 * f, clist ** result)
1115{
1116 char * line;
1117 int res;
1118 clist * list;
1119 int r;
1120 char * name;
1121 clist * param_list;
1122
1123 list = clist_new();
1124 if (list == NULL) {
1125 res = MAILPOP3_NO_ERROR;
1126 goto err;
1127 }
1128
1129 while (1) {
1130 char * next_token;
1131 char * param;
1132 struct mailpop3_capa * capa;
1133
1134 line = read_line(f);
1135 if (line == NULL) {
1136 res = MAILPOP3_ERROR_STREAM;
1137 goto free_list;
1138 }
1139
1140 if (mailstream_is_end_multiline(line))
1141 break;
1142
1143 next_token = cut_token(line);
1144 name = strdup(line);
1145 if (name == NULL) {
1146 res = MAILPOP3_ERROR_MEMORY;
1147 goto free_list;
1148 }
1149
1150 param_list = clist_new();
1151 if (param_list == NULL) {
1152 res = MAILPOP3_ERROR_MEMORY;
1153 goto free_capa_name;
1154 }
1155
1156 while (next_token != NULL) {
1157 line = next_token;
1158 next_token = cut_token(line);
1159 param = strdup(line);
1160 if (param == NULL) {
1161 res = MAILPOP3_ERROR_MEMORY;
1162 goto free_param_list;
1163 }
1164 r = clist_append(param_list, param);
1165 if (r < 0) {
1166 free(param);
1167 res = MAILPOP3_ERROR_MEMORY;
1168 goto free_param_list;
1169 }
1170 }
1171
1172 capa = mailpop3_capa_new(name, param_list);
1173 if (capa == NULL) {
1174 res = MAILPOP3_ERROR_MEMORY;
1175 goto free_param_list;
1176 }
1177
1178 r = clist_append(list, capa);
1179 if (r < 0) {
1180 mailpop3_capa_free(capa);
1181 res = MAILPOP3_ERROR_MEMORY;
1182 goto free_list;
1183 }
1184 }
1185
1186 * result = list;
1187
1188 return MAILPOP3_NO_ERROR;
1189
1190 free_param_list:
1191 clist_foreach(param_list, (clist_func) free, NULL);
1192 clist_free(param_list);
1193 free_capa_name:
1194 free(name);
1195 free_list:
1196 clist_foreach(list, (clist_func) mailpop3_capa_free, NULL);
1197 clist_free(list);
1198 err:
1199 return res;
1200}
1201
1202
1203
1204static char * read_line(mailpop3 * f)
1205{
1206 return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer);
1207}
1208
1209static char * read_multiline(mailpop3 * f, size_t size,
1210 MMAPString * multiline_buffer)
1211{
1212 return mailstream_read_multiline(f->pop3_stream, size,
1213 f->pop3_stream_buffer, multiline_buffer,
1214 f->pop3_progr_rate, f->pop3_progr_fun);
1215}
1216
1217static int send_command(mailpop3 * f, char * command)
1218{
1219 ssize_t r;
1220
1221 r = mailstream_write(f->pop3_stream, command, strlen(command));
1222 if (r == -1)
1223 return -1;
1224
1225 r = mailstream_flush(f->pop3_stream);
1226 if (r == -1)
1227 return -1;
1228
1229 return 0;
1230}
diff --git a/libetpan/src/low-level/pop3/mailpop3.h b/libetpan/src/low-level/pop3/mailpop3.h
new file mode 100644
index 0000000..62275f8
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3.h
@@ -0,0 +1,101 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_H
37
38#define MAILPOP3_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailpop3_types.h>
45
46#include <libetpan/mailpop3_helper.h>
47
48#include <libetpan/mailpop3_socket.h>
49#include <libetpan/mailpop3_ssl.h>
50
51#define POP3_STRING_SIZE 513
52
53mailpop3 * mailpop3_new(size_t pop3_progr_rate,
54 progress_function * pop3_progr_fun);
55
56void mailpop3_free(mailpop3 * f);
57
58int mailpop3_connect(mailpop3 * f, mailstream * s);
59
60int mailpop3_quit(mailpop3 * f);
61
62
63int mailpop3_apop(mailpop3 * f, const char * user, const char * password);
64
65int mailpop3_user(mailpop3 * f, const char * user);
66
67int mailpop3_pass(mailpop3 * f, const char * password);
68
69void mailpop3_list(mailpop3 * f, carray ** result);
70
71int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result,
72 size_t * result_len);
73
74int mailpop3_top(mailpop3 * f, unsigned int index,
75 unsigned int count, char ** result,
76 size_t * result_len);
77
78int mailpop3_dele(mailpop3 * f, unsigned int index);
79
80int mailpop3_noop(mailpop3 * f);
81
82int mailpop3_rset(mailpop3 * f);
83
84void mailpop3_top_free(char * str);
85
86void mailpop3_retr_free(char * str);
87
88int mailpop3_get_msg_info(mailpop3 * f, unsigned int index,
89 struct mailpop3_msg_info ** result);
90
91int mailpop3_capa(mailpop3 * f, clist ** result);
92
93void mailpop3_capa_resp_free(clist * capa_list);
94
95int mailpop3_stls(mailpop3 * f);
96
97#ifdef __cplusplus
98}
99#endif
100
101#endif
diff --git a/libetpan/src/low-level/pop3/mailpop3_helper.c b/libetpan/src/low-level/pop3/mailpop3_helper.c
new file mode 100644
index 0000000..ada97b9
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_helper.c
@@ -0,0 +1,78 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailpop3_helper.h"
37
38#include <string.h>
39
40int mailpop3_login_apop(mailpop3 * f,
41 char * user,
42 char * password)
43{
44 return mailpop3_apop(f, user, password);
45}
46
47
48/*
49 mailpop3_login
50
51 must be used immediately after connect
52*/
53
54int mailpop3_login(mailpop3 * f,
55 char * user,
56 char * password)
57{
58 int r;
59
60 if ((r = mailpop3_user(f, user)) != MAILPOP3_NO_ERROR)
61 return r;
62
63 if ((r = mailpop3_pass(f, password)) != MAILPOP3_NO_ERROR)
64 return r;
65
66 return MAILPOP3_NO_ERROR;
67}
68
69void mailpop3_header_free(char * str)
70{
71 mailpop3_top_free(str);
72}
73
74int mailpop3_header(mailpop3 * f, uint32_t index, char ** result,
75 size_t * result_len)
76{
77 return mailpop3_top(f, index, 0, result, result_len);
78}
diff --git a/libetpan/src/low-level/pop3/mailpop3_helper.h b/libetpan/src/low-level/pop3/mailpop3_helper.h
new file mode 100644
index 0000000..cec93da
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_helper.h
@@ -0,0 +1,64 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_HELPER_H
37
38#define MAILPOP3_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailpop3.h"
45
46int mailpop3_login_apop(mailpop3 * f,
47 char * user,
48 char * password);
49
50int mailpop3_login(mailpop3 * f,
51 char * user,
52 char * password);
53
54int mailpop3_header(mailpop3 * f, uint32_t index, char ** result,
55 size_t * result_len);
56
57void mailpop3_header_free(char * str);
58
59#ifdef __cplusplus
60}
61#endif
62
63#endif
64
diff --git a/libetpan/src/low-level/pop3/mailpop3_socket.c b/libetpan/src/low-level/pop3/mailpop3_socket.c
new file mode 100644
index 0000000..5625f6e
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_socket.c
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailpop3_socket.h"
37
38#include "mailpop3.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_POP3_PORT 110
45#define SERVICE_NAME_POP3 "pop3"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port)
49{
50 int s;
51 mailstream * stream;
52
53 if (port == 0) {
54 port = mail_get_service_port(SERVICE_NAME_POP3, SERVICE_TYPE_TCP);
55 if (port == 0)
56 port = DEFAULT_POP3_PORT;
57 port = ntohs(port);
58 }
59
60 /* Connection */
61
62 s = mail_tcp_connect(server, port);
63 if (s == -1)
64 return MAILPOP3_ERROR_CONNECTION_REFUSED;
65
66 stream = mailstream_socket_open(s);
67 if (stream == NULL) {
68 close(s);
69 return MAILPOP3_ERROR_MEMORY;
70 }
71
72 return mailpop3_connect(f, stream);
73}
diff --git a/libetpan/src/low-level/pop3/mailpop3_socket.h b/libetpan/src/low-level/pop3/mailpop3_socket.h
new file mode 100644
index 0000000..262b2ab
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_socket.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_SOCKET_H
37
38#define MAILPOP3_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailpop3_types.h>
47
48int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/low-level/pop3/mailpop3_ssl.c b/libetpan/src/low-level/pop3/mailpop3_ssl.c
new file mode 100644
index 0000000..fda6073
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_ssl.c
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailpop3_ssl.h"
37
38#include "mailpop3.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_POP3S_PORT 995
45#define SERVICE_NAME_POP3S "pop3s"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port)
49{
50 int s;
51 mailstream * stream;
52
53 if (port == 0) {
54 port = mail_get_service_port(SERVICE_NAME_POP3S, SERVICE_TYPE_TCP);
55 if (port == 0)
56 port = DEFAULT_POP3S_PORT;
57 port = ntohs(port);
58 }
59
60 /* Connection */
61
62 s = mail_tcp_connect(server, port);
63 if (s == -1)
64 return MAILPOP3_ERROR_CONNECTION_REFUSED;
65
66 stream = mailstream_ssl_open(s);
67 if (stream == NULL) {
68 close(s);
69 return MAILPOP3_ERROR_CONNECTION_REFUSED;
70 }
71
72 return mailpop3_connect(f, stream);
73}
diff --git a/libetpan/src/low-level/pop3/mailpop3_ssl.h b/libetpan/src/low-level/pop3/mailpop3_ssl.h
new file mode 100644
index 0000000..38e0769
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_ssl.h
@@ -0,0 +1,54 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_SSL_H
37
38#define MAILPOP3_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailpop3_types.h>
47
48int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/libetpan/src/low-level/pop3/mailpop3_types.h b/libetpan/src/low-level/pop3/mailpop3_types.h
new file mode 100644
index 0000000..18a68bc
--- a/dev/null
+++ b/libetpan/src/low-level/pop3/mailpop3_types.h
@@ -0,0 +1,107 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILPOP3_TYPES_H
37
38#define MAILPOP3_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailstream.h>
45#include <libetpan/mmapstring.h>
46#include <libetpan/carray.h>
47#include <libetpan/clist.h>
48
49#include <inttypes.h>
50
51enum {
52 MAILPOP3_NO_ERROR = 0,
53 MAILPOP3_ERROR_BAD_STATE,
54 MAILPOP3_ERROR_UNAUTHORIZED,
55 MAILPOP3_ERROR_STREAM,
56 MAILPOP3_ERROR_DENIED,
57 MAILPOP3_ERROR_BAD_USER,
58 MAILPOP3_ERROR_BAD_PASSWORD,
59 MAILPOP3_ERROR_CANT_LIST,
60 MAILPOP3_ERROR_NO_SUCH_MESSAGE,
61 MAILPOP3_ERROR_MEMORY,
62 MAILPOP3_ERROR_CONNECTION_REFUSED,
63 MAILPOP3_ERROR_APOP_NOT_SUPPORTED,
64 MAILPOP3_ERROR_CAPA_NOT_SUPPORTED,
65 MAILPOP3_ERROR_STLS_NOT_SUPPORTED,
66};
67
68struct mailpop3
69{
70 char * pop3_response; /* response message */
71 char * pop3_timestamp; /* connection timestamp */
72
73 /* internals */
74 mailstream * pop3_stream;
75 size_t pop3_progr_rate;
76 progress_function * pop3_progr_fun;
77
78 MMAPString * pop3_stream_buffer; /* buffer for lines reading */
79 MMAPString * pop3_response_buffer; /* buffer for responses */
80
81 carray * pop3_msg_tab; /* list of pop3_msg_info structures */
82 int pop3_state; /* state */
83
84 unsigned int pop3_deleted_count;
85};
86
87typedef struct mailpop3 mailpop3;
88
89struct mailpop3_msg_info
90{
91 unsigned int msg_index;
92 uint32_t msg_size;
93 char * msg_uidl;
94 int msg_deleted;
95};
96
97
98struct mailpop3_capa {
99 char * cap_name;
100 clist * cap_param; /* (char *) */
101};
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif
diff --git a/libetpan/src/low-level/smtp/TODO b/libetpan/src/low-level/smtp/TODO
new file mode 100644
index 0000000..96f44c6
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/TODO
@@ -0,0 +1 @@
- STARTTLS
diff --git a/libetpan/src/low-level/smtp/mailsmtp.c b/libetpan/src/low-level/smtp/mailsmtp.c
new file mode 100644
index 0000000..85659e9
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp.c
@@ -0,0 +1,984 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa,
5 * All rights reserved.
6 *
7 * SMTP AUTH support by Juergen Graf
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the libEtPan! project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * $Id$
36 */
37
38#include "mailsmtp.h"
39#include "connect.h"
40#include "md5.h"
41#include "base64.h"
42#include "mail.h"
43
44#include <netinet/in.h>
45#include <string.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <stdio.h>
49
50
51/*
52 RFC 2821 : SMTP
53 RFC 1891 : SMTP Service Extension for Delivery Status Notifications
54
55 RFC 1428 : Transition of Internet Mail from Just-Send-8 to 8bit-SMTP/MIME
56 RFC 1652 : SMTP Service Extension for 8bit-MIMEtransport
57 RFC 1845 : SMTP Service Extension for Checkpoint/Restart
58 RFC 1846 : SMTP 521 Reply Code
59 RFC 1870 : SMTP Service Extension for Message Size Declaration
60 RFC 1985 : SMTP Service Extension for Remote Message Queue Starting
61 RFC 2034 : SMTP Service Extension for Returning Enhanced Error Codes
62 RFC 2442 : The Batch SMTP Media Type
63 RFC 2487 : SMTP Service Extension for Secure SMTP over TLS
64 RFC 2505 : Anti-Spam Recommendations for SMTP MTAs
65 RFC 2554 : SMTP Service Extension for Authentication
66 RFC 2645 : ON-DEMAND MAIL RELAY (ODMR) SMTP with Dynamic IP Addresses
67 RFC 2852 : Deliver By SMTP Service Extension
68 RFC 2920 : SMTP Service Extension for Command Pipelining
69 RFC 3030 : SMTP Service Extensions for Transmission of Large and Binary MIME
70 Messages
71*/
72
73#define SMTP_STATUS_CONTINUE 0x1000
74
75mailsmtp * mailsmtp_new(size_t progr_rate,
76 progress_function * progr_fun)
77{
78 mailsmtp * session;
79
80 session = malloc(sizeof(* session));
81 if (session == NULL)
82 goto err;
83
84 session->stream = NULL;
85
86 session->progr_rate = progr_rate;
87 session->progr_fun = progr_fun;
88
89 session->response = NULL;
90
91 session->line_buffer = mmap_string_new("");
92 if (session->line_buffer == NULL)
93 goto free_session;
94
95 session->response_buffer = mmap_string_new("");
96 if (session->response_buffer == NULL)
97 goto free_line_buffer;
98
99 session->esmtp = 0;
100 session->auth = MAILSMTP_AUTH_NOT_CHECKED;
101
102 return session;
103
104 free_line_buffer:
105 mmap_string_free(session->line_buffer);
106 free_session:
107 free(session);
108 err:
109 return NULL;
110}
111
112void mailsmtp_free(mailsmtp * session)
113{
114 if (session->stream)
115 mailsmtp_quit(session);
116
117 mmap_string_free(session->line_buffer);
118 mmap_string_free(session->response_buffer);
119 free(session);
120}
121
122static int send_command(mailsmtp * f, char * command);
123
124static int read_response(mailsmtp * session);
125
126/* smtp operations */
127
128int mailsmtp_connect(mailsmtp * session, mailstream * s)
129{
130 int code;
131
132 session->stream = s;
133
134 code = read_response(session);
135
136 switch (code) {
137 case 220:
138 return MAILSMTP_NO_ERROR;
139
140 case 554:
141 session->stream = NULL;
142 mailstream_close(s);
143 return MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE;
144
145 default:
146 session->stream = NULL;
147 mailstream_close(s);
148 return MAILSMTP_ERROR_UNEXPECTED_CODE;
149 }
150}
151
152
153#define SMTP_STRING_SIZE 513
154
155int mailsmtp_quit(mailsmtp * session)
156{
157 char command[SMTP_STRING_SIZE];
158 int r;
159
160 snprintf(command, SMTP_STRING_SIZE, "QUIT\r\n");
161 r = send_command(session, command);
162 if (r == -1)
163 return MAILSMTP_ERROR_STREAM;
164 r = read_response(session);
165 if (r == 0)
166 return MAILSMTP_ERROR_STREAM;
167 mailstream_close(session->stream);
168 session->stream = NULL;
169
170 return MAILSMTP_NO_ERROR;
171}
172
173
174
175#define HOSTNAME_SIZE 256
176
177int mailsmtp_helo(mailsmtp * session)
178{
179 int r;
180 char hostname[HOSTNAME_SIZE];
181 char command[SMTP_STRING_SIZE];
182
183 r = gethostname(hostname, HOSTNAME_SIZE);
184 if (r < 0)
185 return MAILSMTP_ERROR_HOSTNAME;
186
187 snprintf(command, SMTP_STRING_SIZE, "HELO %s\r\n", hostname);
188 r = send_command(session, command);
189 if (r == -1)
190 return MAILSMTP_ERROR_STREAM;
191 r = read_response(session);
192
193 switch (r) {
194 case 250:
195 session->esmtp = 0;
196 session->auth = MAILSMTP_AUTH_NOT_CHECKED;
197 return MAILSMTP_NO_ERROR;
198
199 case 504:
200 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
201
202 case 550:
203 return MAILSMTP_ERROR_ACTION_NOT_TAKEN;
204
205 case 0:
206 return MAILSMTP_ERROR_STREAM;
207
208 default:
209 return MAILSMTP_ERROR_UNEXPECTED_CODE;
210 }
211}
212
213int mailsmtp_mail(mailsmtp * session, const char * from)
214{
215 int r;
216 char command[SMTP_STRING_SIZE];
217
218 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>\r\n", from);
219 r = send_command(session, command);
220 if (r == -1)
221 return MAILSMTP_ERROR_STREAM;
222 r = read_response(session);
223
224 switch (r) {
225 case 250:
226 return MAILSMTP_NO_ERROR;
227
228 case 552:
229 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
230
231 case 451:
232 return MAILSMTP_ERROR_IN_PROCESSING;
233
234 case 452:
235 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
236
237 case 550:
238 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
239
240 case 553:
241 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
242
243 case 503:
244 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
245
246 case 0:
247 return MAILSMTP_ERROR_STREAM;
248
249 default:
250 return MAILSMTP_ERROR_UNEXPECTED_CODE;
251 }
252}
253
254int mailsmtp_rcpt(mailsmtp * session, const char * to)
255{
256 return mailesmtp_rcpt(session, to, 0, NULL);
257}
258
259int mailsmtp_data(mailsmtp * session)
260{
261 int r;
262 char command[SMTP_STRING_SIZE];
263
264 snprintf(command, SMTP_STRING_SIZE, "DATA\r\n");
265 r = send_command(session, command);
266 if (r == -1)
267 return MAILSMTP_ERROR_STREAM;
268 r = read_response(session);
269
270 switch (r) {
271 case 354:
272 return MAILSMTP_NO_ERROR;
273
274 case 451:
275 return MAILSMTP_ERROR_IN_PROCESSING;
276
277 case 554:
278 return MAILSMTP_ERROR_TRANSACTION_FAILED;
279
280 case 503:
281 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
282
283 default:
284 return MAILSMTP_ERROR_UNEXPECTED_CODE;
285 }
286}
287
288static int send_data(mailsmtp * session, const char * message, size_t size);
289
290int mailsmtp_data_message(mailsmtp * session,
291 const char * message,
292 size_t size)
293{
294 int r;
295
296 r = send_data(session, message, size);
297 if (r == -1)
298 return MAILSMTP_ERROR_STREAM;
299
300 r = read_response(session);
301
302 switch(r) {
303 case 250:
304 return MAILSMTP_NO_ERROR;
305
306 case 552:
307 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
308
309 case 554:
310 return MAILSMTP_ERROR_TRANSACTION_FAILED;
311
312 case 451:
313 return MAILSMTP_ERROR_IN_PROCESSING;
314
315 case 452:
316 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
317
318 case 0:
319 return MAILSMTP_ERROR_STREAM;
320
321 default:
322 return MAILSMTP_ERROR_UNEXPECTED_CODE;
323 }
324}
325
326/* esmtp operations */
327
328
329/**
330 * called during mailesmtp_ehlo
331 * checks EHLO answer for server extensions and sets flags
332 * in session->esmtp
333 * checks AUTH methods in session->response and sets flags
334 * in session->auth
335 */
336#define isdelim(x) ((x) == ' ' || (x) == '\r' || (x) == '\n' || (x) == '\0')
337
338int mailesmtp_parse_ehlo(mailsmtp * session)
339{
340 char * response;
341
342 /* restore data */
343 session->esmtp = MAILSMTP_ESMTP;
344 session->auth = MAILSMTP_AUTH_CHECKED;
345
346 response = session->response;
347
348 /* ESMTP supported extensions :
349 DSN
350 EXPN
351 8BITMIME
352 SIZE [<n>]
353 ETRN
354 STARTTLS
355 AUTH <mechanisms...>
356 */
357 while (response != NULL) {
358 if (!strncasecmp(response, "EXPN", 4) && isdelim(response[4]))
359 session->esmtp |= MAILSMTP_ESMTP_EXPN;
360 else if (!strncasecmp(response, "ETRN", 4) && isdelim(response[4]))
361 session->esmtp |= MAILSMTP_ESMTP_ETRN;
362 else if (!strncasecmp(response, "DSN", 3) && isdelim(response[3]))
363 session->esmtp |= MAILSMTP_ESMTP_DSN;
364 else if (!strncasecmp(response, "8BITMIME", 8) && isdelim(response[8]))
365 session->esmtp |= MAILSMTP_ESMTP_8BITMIME;
366 else if (!strncasecmp(response, "STARTTLS", 8) && isdelim(response[8]))
367 session->esmtp |= MAILSMTP_ESMTP_STARTTLS;
368 else if (!strncasecmp(response, "SIZE", 4) && isdelim(response[4])) {
369 session->esmtp |= MAILSMTP_ESMTP_SIZE;
370 /* TODO: grab optionnal max size */
371 } else if (!strncasecmp(response, "AUTH ", 5)) {
372 response += 5; /* remove "AUTH " */
373 while (response[0] != '\n' && response[0] != '\0') {
374 while (response[0] == ' ') response++;
375 if (strncasecmp(response, "LOGIN", 5) == 0) {
376 session->auth |= MAILSMTP_AUTH_LOGIN;
377 response += 5;
378 } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) {
379 session->auth |= MAILSMTP_AUTH_CRAM_MD5;
380 response += 8;
381 } else if (strncasecmp(response, "PLAIN", 5) == 0) {
382 session->auth |= MAILSMTP_AUTH_PLAIN;
383 response += 5;
384 } else {
385 /* unknown auth method - jump to next word or eol */
386 while (!isdelim(response[0]) || response[0] == '\r')
387 response++;
388 }
389 }
390 }
391 response = strpbrk(response, "\n");
392 if (response != NULL)
393 response++;
394 }
395
396 return MAILSMTP_NO_ERROR;
397}
398
399
400int mailesmtp_ehlo(mailsmtp * session)
401{
402 int r;
403 char hostname[HOSTNAME_SIZE];
404 char command[SMTP_STRING_SIZE];
405
406 r = gethostname(hostname, HOSTNAME_SIZE);
407 if (r != 0)
408 return MAILSMTP_ERROR_HOSTNAME;
409
410 snprintf(command, SMTP_STRING_SIZE, "EHLO %s\r\n", hostname);
411 r = send_command(session, command);
412 if (r == -1)
413 return MAILSMTP_ERROR_STREAM;
414 r = read_response(session);
415
416 switch (r) {
417 case 250:
418 return mailesmtp_parse_ehlo(session);
419
420 case 504:
421 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
422
423 case 550:
424 return MAILSMTP_ERROR_ACTION_NOT_TAKEN;
425
426 case 0:
427 return MAILSMTP_ERROR_STREAM;
428
429 default:
430 return MAILSMTP_ERROR_UNEXPECTED_CODE;
431 }
432}
433
434/*
435 if return_full is TRUE, the entire message is returned on error
436 envid can be NULL
437*/
438
439
440int mailesmtp_mail(mailsmtp * session,
441 const char * from,
442 int return_full,
443 const char * envid)
444{
445 int r;
446 char command[SMTP_STRING_SIZE];
447 char *body = "";
448
449#if notyet
450 /* TODO: figure out a way for the user to explicity enable this or not */
451 if (session->esmtp & MAILSMTP_ESMTP_8BITMIME)
452 body = " BODY=8BITMIME";
453#endif
454
455 if (session->esmtp & MAILSMTP_ESMTP_DSN) {
456 if (envid)
457 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s ENVID=%s%s\r\n",
458 from, return_full ? "FULL" : "HDRS", envid, body);
459 else
460 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s%s\r\n",
461 from, return_full ? "FULL" : "HDRS", body);
462 } else
463 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>%s\r\n",
464 from, body);
465
466 r = send_command(session, command);
467 if (r == -1)
468 return MAILSMTP_ERROR_STREAM;
469 r = read_response(session);
470
471 switch (r) {
472 case 250:
473 return MAILSMTP_NO_ERROR;
474
475 case 552:
476 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
477
478 case 451:
479 return MAILSMTP_ERROR_IN_PROCESSING;
480
481 case 452:
482 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
483
484 case 550:
485 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
486
487 case 553:
488 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
489
490 case 503:
491 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
492
493 case 0:
494 return MAILSMTP_ERROR_STREAM;
495
496 default:
497 return MAILSMTP_ERROR_UNEXPECTED_CODE;
498 }
499}
500
501int mailesmtp_rcpt(mailsmtp * session,
502 const char * to,
503 int notify,
504 const char * orcpt)
505{
506 int r;
507 char command[SMTP_STRING_SIZE];
508 char notify_str[30] = "";
509 char notify_info_str[30] = "";
510
511 if (notify != 0 && session->esmtp & MAILSMTP_ESMTP_DSN) {
512 if (notify & MAILSMTP_DSN_NOTIFY_SUCCESS)
513 strcat(notify_info_str, ",SUCCESS");
514 if (notify & MAILSMTP_DSN_NOTIFY_FAILURE)
515 strcat(notify_info_str, ",FAILURE");
516 if (notify & MAILSMTP_DSN_NOTIFY_DELAY)
517 strcat(notify_info_str, ",DELAY");
518
519 if (notify & MAILSMTP_DSN_NOTIFY_NEVER)
520 strcpy(notify_info_str, ",NEVER");
521
522 notify_info_str[0] = '=';
523
524 strcpy(notify_str, " NOTIFY");
525 strcat(notify_str, notify_info_str);
526 }
527
528 if (orcpt && session->esmtp & MAILSMTP_ESMTP_DSN)
529 snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s ORCPT=%s\r\n",
530 to, notify_str, orcpt);
531 else
532 snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s\r\n", to, notify_str);
533
534 r = send_command(session, command);
535 if (r == -1)
536 return MAILSMTP_ERROR_STREAM;
537 r = read_response(session);
538
539 switch (r) {
540 case 250:
541 return MAILSMTP_NO_ERROR;
542
543 case 251: /* not local user, will be forwarded */
544 return MAILSMTP_NO_ERROR;
545
546 case 550:
547 case 450:
548 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
549
550 case 551:
551 return MAILSMTP_ERROR_USER_NOT_LOCAL;
552
553 case 552:
554 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
555
556 case 553:
557 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
558
559 case 451:
560 return MAILSMTP_ERROR_IN_PROCESSING;
561
562 case 452:
563 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
564
565 case 503:
566 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
567
568 case 0:
569 return MAILSMTP_ERROR_STREAM;
570
571 default:
572 return MAILSMTP_ERROR_UNEXPECTED_CODE;
573 }
574}
575
576int auth_map_errors(int err)
577{
578 switch (err) {
579 case 235:
580 return MAILSMTP_NO_ERROR; /* AUTH successfull */
581 case 334:
582 return MAILSMTP_NO_ERROR; /* AUTH in progress */
583 case 432:
584 return MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED;
585 case 454:
586 return MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE;
587 case 504:
588 return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
589 case 530:
590 return MAILSMTP_ERROR_AUTH_REQUIRED;
591 case 534:
592 return MAILSMTP_ERROR_AUTH_TOO_WEAK;
593 case 538:
594 return MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED;
595 default:
596 /* opportunistic approach ;) */
597 return MAILSMTP_NO_ERROR;
598 }
599}
600
601static int mailsmtp_auth_login(mailsmtp * session,
602 const char * user, const char * pass)
603{
604 int err;
605 char command[SMTP_STRING_SIZE];
606 char * user64, * pass64;
607
608 user64 = NULL;
609 pass64 = NULL;
610
611 user64 = encode_base64(user, strlen(user));
612 if (user64 == NULL) {
613 err = MAILSMTP_ERROR_MEMORY;
614 goto err_free;
615 }
616
617 pass64 = encode_base64(pass, strlen(pass));
618 if (pass64 == NULL) {
619 err = MAILSMTP_ERROR_MEMORY;
620 goto err_free;
621 }
622
623 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", user64);
624 err = send_command(session, command);
625 if (err == -1) {
626 err = MAILSMTP_ERROR_STREAM;
627 goto err_free;
628 }
629 err = read_response(session);
630 err = auth_map_errors(err);
631 if (err != MAILSMTP_NO_ERROR)
632 goto err_free;
633
634 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", pass64);
635 err = send_command(session, command);
636 if (err == -1) {
637 err = MAILSMTP_ERROR_STREAM;
638 goto err_free;
639 }
640 err = read_response(session);
641 err = auth_map_errors(err);
642
643 err_free:
644 free(user64);
645 free(pass64);
646
647 return err;
648}
649
650static int mailsmtp_auth_plain(mailsmtp * session,
651 const char * user, const char * pass)
652{
653 int err, len;
654 char command[SMTP_STRING_SIZE];
655 char * plain, * plain64;
656
657 len = strlen(user) + strlen(pass) + 3;
658 plain = (char *) malloc(len);
659 if (plain == NULL) {
660 err = MAILSMTP_ERROR_MEMORY;
661 goto err;
662 }
663
664 snprintf(plain, len, "%c%s%c%s", '\0', user, '\0', pass);
665 plain64 = encode_base64(plain, len - 1);
666
667 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", plain64);
668 err = send_command(session, command);
669 if (err == -1) {
670 err = MAILSMTP_ERROR_STREAM;
671 goto err_free;
672 }
673
674 err = read_response(session);
675 err = auth_map_errors(err);
676
677err_free:
678 free(plain64);
679 free(plain);
680
681 err:
682 return err;
683}
684
685static char * convert_hex(unsigned char *in, int len)
686{
687 static char hex[] = "0123456789abcdef";
688 char * out;
689 int i;
690
691 out = (char *) malloc(len * 2 + 1);
692 if (out == NULL)
693 return NULL;
694
695 for (i = 0; i < len; i++) {
696 out[i * 2] = hex[in[i] >> 4];
697 out[i * 2 + 1] = hex[in[i] & 15];
698 }
699
700 out[i*2] = 0;
701
702 return out;
703}
704
705static char * hash_md5(const char * sec_key, const char * data, int len)
706{
707 char key[65], digest[24];
708 char * hash_hex;
709
710 int sec_len, i;
711
712 sec_len = strlen(sec_key);
713
714 if (sec_len < 64) {
715 memcpy(key, sec_key, sec_len);
716 for (i = sec_len; i < 64; i++) {
717 key[i] = 0;
718 }
719 } else {
720 memcpy(key, sec_key, 64);
721 }
722
723 hmac_md5(data, len, key, 64, digest);
724 hash_hex = convert_hex(digest, 16);
725
726 return hash_hex;
727}
728
729static int mailsmtp_auth_cram_md5(mailsmtp * session,
730 const char * user, const char * pass)
731{
732 int err;
733 char command[SMTP_STRING_SIZE];
734 char *response, *auth_hex, *auth;
735
736 response = decode_base64(session->response, strlen(session->response));
737 if (response == NULL) return MAILSMTP_ERROR_MEMORY;
738
739 auth_hex = hash_md5(pass, response, strlen(response));
740 if (auth_hex == NULL) {
741 err = MAILSMTP_ERROR_MEMORY;
742 goto err_free_response;
743 }
744
745 snprintf(command, SMTP_STRING_SIZE, "%s %s", user, auth_hex);
746
747 auth = encode_base64(command, strlen(command));
748 if (auth == NULL) {
749 err = MAILSMTP_ERROR_MEMORY;
750 goto err_free_auth_hex;
751 }
752
753 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", auth);
754 err = send_command(session, command);
755 if (err == -1) {
756 err = MAILSMTP_ERROR_STREAM;
757 goto err_free;
758 }
759
760 err = read_response(session);
761 err = auth_map_errors(err);
762
763err_free:
764 free(auth);
765err_free_auth_hex:
766 free(auth_hex);
767err_free_response:
768 free(response);
769 return err;
770}
771
772int mailsmtp_auth_type(mailsmtp * session,
773 const char * user, const char * pass, int type)
774{
775 int err;
776 char command[SMTP_STRING_SIZE];
777
778 if (session->auth == MAILSMTP_AUTH_NOT_CHECKED)
779 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
780
781 if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
782
783 switch (type) {
784 case MAILSMTP_AUTH_LOGIN:
785 snprintf(command, SMTP_STRING_SIZE, "AUTH LOGIN\r\n");
786 break;
787 case MAILSMTP_AUTH_PLAIN:
788 snprintf(command, SMTP_STRING_SIZE, "AUTH PLAIN\r\n");
789 break;
790 case MAILSMTP_AUTH_CRAM_MD5:
791 snprintf(command, SMTP_STRING_SIZE, "AUTH CRAM-MD5\r\n");
792 break;
793 default:
794 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
795 }
796
797 err = send_command(session, command);
798 if (err == -1) return MAILSMTP_ERROR_STREAM;
799
800 err = read_response(session);
801 err = auth_map_errors(err);
802 if (err != MAILSMTP_NO_ERROR) return err;
803
804 switch (type) {
805 case MAILSMTP_AUTH_LOGIN:
806 return mailsmtp_auth_login(session, user, pass);
807 case MAILSMTP_AUTH_PLAIN:
808 return mailsmtp_auth_plain(session, user, pass);
809 case MAILSMTP_AUTH_CRAM_MD5:
810 return mailsmtp_auth_cram_md5(session, user, pass);
811 default:
812 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
813 }
814}
815
816
817int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass)
818{
819 if (session->auth == MAILSMTP_AUTH_NOT_CHECKED)
820 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
821
822 if (session->auth & MAILSMTP_AUTH_CRAM_MD5) {
823 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_CRAM_MD5);
824 } else if (session->auth & MAILSMTP_AUTH_PLAIN) {
825 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_PLAIN);
826 } else if (session->auth & MAILSMTP_AUTH_LOGIN) {
827 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_LOGIN);
828 } else {
829 return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
830 }
831}
832
833/* TODO: add mailesmtp_etrn, mailssmtp_expn */
834
835int mailesmtp_starttls(mailsmtp * session) {
836 int r;
837
838 if (!(session->esmtp & MAILSMTP_ESMTP_STARTTLS))
839 return MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED;
840
841 r = send_command(session, "STARTTLS\r\n");
842 if (r == -1)
843 return MAILSMTP_ERROR_STREAM;
844 r = read_response(session);
845
846 switch (r) {
847 case 220:
848 return MAILSMTP_NO_ERROR;
849
850 case 454:
851 return MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE;
852
853 default:
854 return MAILSMTP_ERROR_UNEXPECTED_CODE;
855 }
856}
857
858static int parse_response(mailsmtp * session,
859 char * response)
860{
861 char * message;
862 int code;
863 int cont = 0;
864
865 code = strtol(response, &message, 10);
866 if (* message == ' ')
867 mmap_string_append(session->response_buffer, message + 1);
868 else if (* message == '-') {
869 cont = SMTP_STATUS_CONTINUE;
870 mmap_string_append(session->response_buffer, message + 1);
871 }
872 else
873 mmap_string_append(session->response_buffer, message);
874
875 return code | cont;
876}
877
878static char * read_line(mailsmtp * session)
879{
880 return mailstream_read_line_remove_eol(session->stream,
881 session->line_buffer);
882}
883
884static int read_response(mailsmtp * session)
885{
886 char * line;
887 int code;
888
889 mmap_string_assign(session->response_buffer, "");
890
891 do {
892 line = read_line(session);
893
894 if (line != NULL) {
895 code = parse_response(session, line);
896 mmap_string_append_c(session->response_buffer, '\n');
897 }
898 else
899 code = 0;
900 }
901 while ((code & SMTP_STATUS_CONTINUE) != 0);
902
903 session->response = session->response_buffer->str;
904
905 return code;
906}
907
908
909
910
911
912static int send_command(mailsmtp * f, char * command)
913{
914 ssize_t r;
915
916 r = mailstream_write(f->stream, command, strlen(command));
917 if (r == -1)
918 return -1;
919
920 r = mailstream_flush(f->stream);
921 if (r == -1)
922 return -1;
923
924 return 0;
925}
926
927static int send_data(mailsmtp * session, const char * message, size_t size)
928{
929 if (mailstream_send_data(session->stream, message, size,
930 session->progr_rate, session->progr_fun) == -1)
931 return -1;
932
933 if (mailstream_flush(session->stream) == -1)
934 return -1;
935
936 return 0;
937}
938
939
940const char * mailsmtp_strerror(int errnum)
941{
942 switch (errnum) {
943 case MAILSMTP_NO_ERROR:
944 return "No error";
945 case MAILSMTP_ERROR_UNEXPECTED_CODE:
946 return "Unexpected error code";
947 case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
948 return "Service not available";
949 case MAILSMTP_ERROR_STREAM:
950 return "Stream error";
951 case MAILSMTP_ERROR_HOSTNAME:
952 return "gethostname() failed";
953 case MAILSMTP_ERROR_NOT_IMPLEMENTED:
954 return "Not implemented";
955 case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
956 return "Error, action not taken";
957 case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
958 return "Data exceeds storage allocation";
959 case MAILSMTP_ERROR_IN_PROCESSING:
960 return "Error in processing";
961 case MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE:
962 return "Insufficient system storage";
963 case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
964 return "Mailbox unavailable";
965 case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
966 return "Mailbox name not allowed";
967 case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
968 return "Bad command sequence";
969 case MAILSMTP_ERROR_USER_NOT_LOCAL:
970 return "User not local";
971 case MAILSMTP_ERROR_TRANSACTION_FAILED:
972 return "Transaction failed";
973 case MAILSMTP_ERROR_MEMORY:
974 return "Memory error";
975 case MAILSMTP_ERROR_CONNECTION_REFUSED:
976 return "Connection refused";
977 case MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE:
978 return "TLS not available on server for temporary reason";
979 case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED:
980 return "TLS not supported by server";
981 default:
982 return "Unknown error code";
983 }
984}
diff --git a/libetpan/src/low-level/smtp/mailsmtp.h b/libetpan/src/low-level/smtp/mailsmtp.h
new file mode 100644
index 0000000..72e1786
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp.h
@@ -0,0 +1,94 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_H
37
38#define MAILSMTP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailsmtp_types.h>
45#include <libetpan/mailsmtp_helper.h>
46#include <libetpan/mailsmtp_socket.h>
47#include <libetpan/mailsmtp_ssl.h>
48
49
50mailsmtp * mailsmtp_new(size_t progr_rate,
51 progress_function * progr_fun);
52void mailsmtp_free(mailsmtp * session);
53
54int mailsmtp_connect(mailsmtp * session, mailstream * s);
55int mailsmtp_quit(mailsmtp * session);
56
57/**
58 * Tries AUTH with detected method - "better" method first:
59 * CRAM-MD5 -> PLAIN -> LOGIN
60 */
61int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass);
62
63/**
64 * tries to autenticate with the server using given auth-type
65 * returns MAILSMTP_NO_ERROR on success
66 */
67int mailsmtp_auth_type(mailsmtp * session,
68 const char * user, const char * pass, int type);
69
70int mailsmtp_helo(mailsmtp * session);
71int mailsmtp_mail(mailsmtp * session, const char * from);
72int mailsmtp_rcpt(mailsmtp * session, const char * to);
73int mailsmtp_data(mailsmtp * session);
74int mailsmtp_data_message(mailsmtp * session,
75 const char * message,
76 size_t size);
77int mailesmtp_ehlo(mailsmtp * session);
78int mailesmtp_mail(mailsmtp * session,
79 const char * from,
80 int return_full,
81 const char * envid);
82int mailesmtp_rcpt(mailsmtp * session,
83 const char * to,
84 int notify,
85 const char * orcpt);
86int mailesmtp_starttls(mailsmtp * session);
87
88const char * mailsmtp_strerror(int errnum);
89
90#ifdef __cplusplus
91}
92#endif
93
94#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_helper.c b/libetpan/src/low-level/smtp/mailsmtp_helper.c
new file mode 100644
index 0000000..69b73cc
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_helper.c
@@ -0,0 +1,228 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp.h"
37#include <string.h>
38#include <stdlib.h>
39#include "mail.h"
40
41int mailsmtp_init(mailsmtp * session)
42{
43 int r;
44
45 r = mailesmtp_ehlo(session);
46
47 if (r == MAILSMTP_NO_ERROR)
48 return MAILSMTP_NO_ERROR;
49
50 r = mailsmtp_helo(session);
51 if (r == MAILSMTP_NO_ERROR)
52 return MAILSMTP_NO_ERROR;
53
54 return r;
55}
56
57
58
59int mailesmtp_send(mailsmtp * session,
60 const char * from,
61 int return_full,
62 const char * envid,
63 clist * addresses,
64 const char * message, size_t size)
65{
66 int r;
67 clistiter * l;
68
69 if (!session->esmtp)
70 return mailsmtp_send(session, from, addresses, message, size);
71
72 r = mailesmtp_mail(session, from, return_full, envid);
73 if (r != MAILSMTP_NO_ERROR)
74 return r;
75
76 for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) {
77 struct esmtp_address * addr;
78
79 addr = clist_content(l);
80
81 r = mailesmtp_rcpt(session, addr->address, addr->notify, addr->orcpt);
82 if (r != MAILSMTP_NO_ERROR)
83 return r;
84 }
85
86 r = mailsmtp_data(session);
87 if (r != MAILSMTP_NO_ERROR)
88 return r;
89
90 r = mailsmtp_data_message(session, message, size);
91 if (r != MAILSMTP_NO_ERROR)
92 return r;
93
94 return MAILSMTP_NO_ERROR;
95}
96
97int mailsmtp_send(mailsmtp * session,
98 const char * from,
99 clist * addresses,
100 const char * message, size_t size)
101{
102 int r;
103 clistiter * l;
104
105 r = mailsmtp_mail(session, from);
106 if (r != MAILSMTP_NO_ERROR)
107 return r;
108
109 for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) {
110 struct esmtp_address * addr;
111
112 addr = clist_content(l);
113
114 r = mailsmtp_rcpt(session, addr->address);
115 if (r != MAILSMTP_NO_ERROR)
116 return r;
117 }
118
119 r = mailsmtp_data(session);
120 if (r != MAILSMTP_NO_ERROR)
121 return r;
122
123 r = mailsmtp_data_message(session, message, size);
124 if (r != MAILSMTP_NO_ERROR)
125 return r;
126
127 return MAILSMTP_NO_ERROR;
128}
129
130
131
132
133
134
135
136
137
138
139
140
141
142/* esmtp addresses and smtp addresses */
143
144static struct esmtp_address * esmtp_address_new(char * addr,
145 int notify, char * orcpt)
146{
147 struct esmtp_address * esmtpa;
148
149 esmtpa = malloc(sizeof(* esmtpa));
150 if (esmtpa == NULL)
151 return NULL;
152
153 esmtpa->address = strdup(addr);
154 if (esmtpa->address == NULL) {
155 free(esmtpa);
156 return NULL;
157 }
158
159 if (orcpt != NULL) {
160 esmtpa->orcpt = strdup(orcpt);
161 if (esmtpa->orcpt == NULL) {
162 free(esmtpa->address);
163 free(esmtpa);
164 return NULL;
165 }
166 }
167 else
168 esmtpa->orcpt = NULL;
169
170 esmtpa->notify = notify;
171
172 return esmtpa;
173}
174
175static void esmtp_address_free(struct esmtp_address * addr)
176{
177 if (addr->orcpt)
178 free(addr->orcpt);
179 if (addr->address)
180 free(addr->address);
181
182 free(addr);
183}
184
185clist * esmtp_address_list_new()
186{
187 return clist_new();
188}
189
190void esmtp_address_list_free(clist * l)
191{
192 clist_foreach(l, (clist_func) esmtp_address_free, NULL);
193 clist_free(l);
194}
195
196int esmtp_address_list_add(clist * list, char * address,
197 int notify, char * orcpt)
198{
199 struct esmtp_address * esmtpa;
200 int r;
201
202 esmtpa = esmtp_address_new(address, notify, orcpt);
203 if (esmtpa == NULL)
204 return -1;
205
206 r = clist_append(list, esmtpa);
207 if (r < 0) {
208 esmtp_address_free(esmtpa);
209 return -1;
210 }
211
212 return 0;
213}
214
215clist * smtp_address_list_new()
216{
217 return esmtp_address_list_new();
218}
219
220int smtp_address_list_add(clist * list, char * address)
221{
222 return esmtp_address_list_add(list, address, 0, NULL);
223}
224
225void smtp_address_list_free(clist * l)
226{
227 esmtp_address_list_free(l);
228}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_helper.h b/libetpan/src/low-level/smtp/mailsmtp_helper.h
new file mode 100644
index 0000000..2178d50
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_helper.h
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_HELPER_H
37
38#define MAILSMTP_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailsmtp_types.h"
45#include "clist.h"
46
47int mailsmtp_init(mailsmtp * session);
48
49int mailesmtp_send(mailsmtp * session,
50 const char * from,
51 int return_full,
52 const char * envid,
53 clist * addresses,
54 const char * message, size_t size);
55
56int mailsmtp_send(mailsmtp * session,
57 const char * from,
58 clist * addresses,
59 const char * message, size_t size);
60
61clist * esmtp_address_list_new();
62int esmtp_address_list_add(clist * list, char * address,
63 int notify, char * orcpt);
64void esmtp_address_list_free(clist * l);
65
66clist * smtp_address_list_new();
67int smtp_address_list_add(clist * list, char * address);
68void smtp_address_list_free(clist * l);
69
70#ifdef __cplusplus
71}
72#endif
73
74#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_socket.c b/libetpan/src/low-level/smtp/mailsmtp_socket.c
new file mode 100644
index 0000000..6b8d81a
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_socket.c
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp_socket.h"
37
38#include "mailsmtp.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_SMTP_PORT 25
45#define SERVICE_NAME_SMTP "smtp"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailsmtp_socket_connect(mailsmtp * session,
49 const char * server, uint16_t port)
50{
51 int s;
52 mailstream * stream;
53
54 if (port == 0) {
55 port = mail_get_service_port(SERVICE_NAME_SMTP, SERVICE_TYPE_TCP);
56 if (port == 0)
57 port = DEFAULT_SMTP_PORT;
58 port = ntohs(port);
59 }
60
61 /* Connection */
62
63 s = mail_tcp_connect(server, port);
64 if (s == -1)
65 return MAILSMTP_ERROR_CONNECTION_REFUSED;
66
67 stream = mailstream_socket_open(s);
68 if (stream == NULL) {
69 close(s);
70 return MAILSMTP_ERROR_MEMORY;
71 }
72
73 return mailsmtp_connect(session, stream);
74}
75
76int mailsmtp_socket_starttls(mailsmtp * session) {
77 int r;
78 int fd;
79 mailstream_low * low;
80 mailstream_low * new_low;
81
82 r = mailesmtp_starttls(session);
83 if (r != MAILSMTP_NO_ERROR)
84 return r;
85
86 low = mailstream_get_low(session->stream);
87 fd = mailstream_low_get_fd(low);
88 if (fd == -1)
89 return MAILSMTP_ERROR_STREAM;
90
91 new_low = mailstream_low_ssl_open(fd);
92 if (new_low == NULL)
93 return MAILSMTP_ERROR_STREAM;
94
95 mailstream_low_free(low);
96 mailstream_set_low(session->stream, new_low);
97
98 return MAILSMTP_NO_ERROR;
99}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_socket.h b/libetpan/src/low-level/smtp/mailsmtp_socket.h
new file mode 100644
index 0000000..2726c1d
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_socket.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SOCKET_H
37
38#define MAILSMTP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_socket_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50int mailsmtp_socket_starttls(mailsmtp * session);
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_ssl.c b/libetpan/src/low-level/smtp/mailsmtp_ssl.c
new file mode 100644
index 0000000..4a42326
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_ssl.c
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp_socket.h"
37
38#include "mailsmtp.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_SMTPS_PORT 465
45#define SERVICE_NAME_SMTPS "smtps"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailsmtp_ssl_connect(mailsmtp * session,
49 const char * server, uint16_t port)
50{
51 int s;
52 mailstream * stream;
53
54 if (port == 0) {
55 port = mail_get_service_port(SERVICE_NAME_SMTPS, SERVICE_TYPE_TCP);
56 if (port == 0)
57 port = DEFAULT_SMTPS_PORT;
58 port = ntohs(port);
59 }
60
61 /* Connection */
62
63 s = mail_tcp_connect(server, port);
64 if (s == -1)
65 return MAILSMTP_ERROR_CONNECTION_REFUSED;
66
67 stream = mailstream_ssl_open(s);
68 if (stream == NULL) {
69 close(s);
70 return MAILSMTP_ERROR_CONNECTION_REFUSED;
71 }
72
73 return mailsmtp_connect(session, stream);
74}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_ssl.h b/libetpan/src/low-level/smtp/mailsmtp_ssl.h
new file mode 100644
index 0000000..01f4683
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_ssl.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SSL_H
37
38#define MAILSMTP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_ssl_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_types.h b/libetpan/src/low-level/smtp/mailsmtp_types.h
new file mode 100644
index 0000000..0aa2617
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_types.h
@@ -0,0 +1,126 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_TYPES_H
37
38#define MAILSMTP_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstream.h"
45#include "mmapstring.h"
46
47enum {
48 MAILSMTP_NO_ERROR = 0,
49 MAILSMTP_ERROR_UNEXPECTED_CODE,
50 MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE,
51 MAILSMTP_ERROR_STREAM,
52 MAILSMTP_ERROR_HOSTNAME,
53 MAILSMTP_ERROR_NOT_IMPLEMENTED,
54 MAILSMTP_ERROR_ACTION_NOT_TAKEN,
55 MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION,
56 MAILSMTP_ERROR_IN_PROCESSING,
57 MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE,
58 MAILSMTP_ERROR_MAILBOX_UNAVAILABLE,
59 MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED,
60 MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND,
61 MAILSMTP_ERROR_USER_NOT_LOCAL,
62 MAILSMTP_ERROR_TRANSACTION_FAILED,
63 MAILSMTP_ERROR_MEMORY,
64 MAILSMTP_ERROR_AUTH_NOT_SUPPORTED,
65 MAILSMTP_ERROR_AUTH_LOGIN,
66 MAILSMTP_ERROR_AUTH_REQUIRED,
67 MAILSMTP_ERROR_AUTH_TOO_WEAK,
68 MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED,
69 MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE,
70 MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED,
71 MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE,
72 MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED,
73 MAILSMTP_ERROR_CONNECTION_REFUSED
74};
75
76enum {
77 MAILSMTP_AUTH_NOT_CHECKED = 0,
78 MAILSMTP_AUTH_CHECKED = 1,
79 MAILSMTP_AUTH_CRAM_MD5 = 2,
80 MAILSMTP_AUTH_PLAIN = 4,
81 MAILSMTP_AUTH_LOGIN = 8
82};
83
84enum {
85 MAILSMTP_ESMTP = 1,
86 MAILSMTP_ESMTP_EXPN = 2,
87 MAILSMTP_ESMTP_8BITMIME = 4,
88 MAILSMTP_ESMTP_SIZE = 8,
89 MAILSMTP_ESMTP_ETRN = 16,
90 MAILSMTP_ESMTP_STARTTLS = 32,
91 MAILSMTP_ESMTP_DSN = 64,
92};
93
94struct mailsmtp {
95 mailstream * stream;
96
97 size_t progr_rate;
98 progress_function * progr_fun;
99
100 char * response;
101
102 MMAPString * line_buffer;
103 MMAPString * response_buffer;
104
105 int esmtp; // contains flags MAILSMTP_ESMTP_*
106 int auth; // contains flags MAILSMTP_AUTH_*
107};
108
109typedef struct mailsmtp mailsmtp;
110
111#define MAILSMTP_DSN_NOTIFY_SUCCESS 1
112#define MAILSMTP_DSN_NOTIFY_FAILURE 2
113#define MAILSMTP_DSN_NOTIFY_DELAY 4
114#define MAILSMTP_DSN_NOTIFY_NEVER 8
115
116struct esmtp_address {
117 char * address;
118 int notify;
119 char * orcpt;
120};
121
122#ifdef __cplusplus
123}
124#endif
125
126#endif
diff --git a/libetpan/src/main/libetpan.h b/libetpan/src/main/libetpan.h
new file mode 100644
index 0000000..c58bede
--- a/dev/null
+++ b/libetpan/src/main/libetpan.h
@@ -0,0 +1,119 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef LIBETPAN_H
37
38#define LIBETPAN_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/libetpan_version.h>
45#include <libetpan/maildriver.h>
46#include <libetpan/mailmessage.h>
47#include <libetpan/mailfolder.h>
48#include <libetpan/mailstorage.h>
49#include <libetpan/mailthread.h>
50#include <libetpan/mailsmtp.h>
51#include <libetpan/charconv.h>
52
53/* mbox driver */
54#include <libetpan/mboxdriver.h>
55#include <libetpan/mboxdriver_message.h>
56#include <libetpan/mboxdriver_cached.h>
57#include <libetpan/mboxdriver_cached_message.h>
58#include <libetpan/mboxstorage.h>
59
60/* MH driver */
61#include <libetpan/mhdriver.h>
62#include <libetpan/mhdriver_message.h>
63#include <libetpan/mhdriver_cached.h>
64#include <libetpan/mhdriver_cached_message.h>
65#include <libetpan/mhstorage.h>
66
67/* IMAP4rev1 driver */
68#include <libetpan/imapdriver.h>
69#include <libetpan/imapdriver_message.h>
70#include <libetpan/imapdriver_cached.h>
71#include <libetpan/imapdriver_cached_message.h>
72#include <libetpan/imapstorage.h>
73
74/* POP3 driver */
75#include <libetpan/pop3driver.h>
76#include <libetpan/pop3driver_message.h>
77#include <libetpan/pop3driver_cached.h>
78#include <libetpan/pop3driver_cached_message.h>
79#include <libetpan/pop3storage.h>
80
81/* Hotmail */
82#include <libetpan/hotmailstorage.h>
83
84/* NNTP driver */
85#include <libetpan/nntpdriver.h>
86#include <libetpan/nntpdriver_message.h>
87#include <libetpan/nntpdriver_cached.h>
88#include <libetpan/nntpdriver_cached_message.h>
89#include <libetpan/nntpstorage.h>
90
91/* maildir driver */
92#include <libetpan/maildirdriver.h>
93#include <libetpan/maildirdriver_message.h>
94#include <libetpan/maildirdriver_cached.h>
95#include <libetpan/maildirdriver_cached_message.h>
96#include <libetpan/maildirstorage.h>
97
98/* db driver */
99#include <libetpan/dbdriver.h>
100#include <libetpan/dbdriver_message.h>
101#include <libetpan/dbstorage.h>
102
103/* message which content is given by a MIME structure */
104#include <libetpan/mime_message_driver.h>
105
106/* message which content given by a string */
107#include <libetpan/data_message_driver.h>
108
109/* engine */
110#include <libetpan/mailprivacy.h>
111#include <libetpan/mailengine.h>
112#include <libetpan/mailprivacy_gnupg.h>
113#include <libetpan/mailprivacy_smime.h>
114
115#ifdef __cplusplus
116}
117#endif
118
119#endif
diff --git a/libetpan/src/main/libetpan_version.c b/libetpan/src/main/libetpan_version.c
new file mode 100644
index 0000000..9f475db
--- a/dev/null
+++ b/libetpan/src/main/libetpan_version.c
@@ -0,0 +1,53 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001 - 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "libetpan_version.h"
37
38#ifndef CONFIG_H
39#define CONFIG_H
40#include "config.h"
41#endif
42
43/* version of libEtPan! at runtime */
44
45int libetpan_get_version_major(void)
46{
47 return LIBETPAN_VERSION_MAJOR;
48}
49
50int libetpan_get_version_minor(void)
51{
52 return LIBETPAN_VERSION_MINOR;
53}
diff --git a/libetpan/src/main/libetpan_version.h b/libetpan/src/main/libetpan_version.h
new file mode 100644
index 0000000..c1737d1
--- a/dev/null
+++ b/libetpan/src/main/libetpan_version.h
@@ -0,0 +1,57 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001 - 2003 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef LIBETPAN_VERSION_H
37
38#define LIBETPAN_VERSION_H
39
40#ifndef LIBETPAN_VERSION_MAJOR
41#define LIBETPAN_VERSION_MAJOR 0
42#endif
43
44#ifndef LIBETPAN_VERSION_MINOR
45#define LIBETPAN_VERSION_MINOR 36
46#endif
47
48#ifndef LIBETPAN_REENTRANT
49#if 1
50#define LIBETPAN_REENTRANT 1
51#endif
52#endif
53
54int libetpan_get_version_major(void);
55int libetpan_get_version_minor(void);
56
57#endif
diff --git a/libetpan/src/main/libetpan_version.h.in b/libetpan/src/main/libetpan_version.h.in
new file mode 100644
index 0000000..c8fe511
--- a/dev/null
+++ b/libetpan/src/main/libetpan_version.h.in
@@ -0,0 +1,57 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001 - 2003 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef LIBETPAN_VERSION_H
37
38#define LIBETPAN_VERSION_H
39
40#ifndef LIBETPAN_VERSION_MAJOR
41#define LIBETPAN_VERSION_MAJOR @VERSION_MAJOR@
42#endif
43
44#ifndef LIBETPAN_VERSION_MINOR
45#define LIBETPAN_VERSION_MINOR @VERSION_MINOR@
46#endif
47
48#ifndef LIBETPAN_REENTRANT
49#if @REENTRANT@
50#define LIBETPAN_REENTRANT 1
51#endif
52#endif
53
54int libetpan_get_version_major(void);
55int libetpan_get_version_minor(void);
56
57#endif